• Welcome to Valhalla Legends Archive.
 

String Pointer Causing Access Violation

Started by Dyndrilliac, June 10, 2005, 11:51 AM

Previous topic - Next topic

Dyndrilliac

#include <string.h>

class String {
  public:
    String(char *strText);
    void fSetString(char *strText);
    char *fGetText();
    int fGetLen();
    bool fCompareTo(char *strText);
  private:
    char *szText;
    int iLength;
};

String::String(char *strText) {
    szText = strText;
    iLength = strlen(strText);
}

void String::fSetString(char *strText) {
    szText = strText;
    iLength = strlen(strText);
}

char *String::fGetText() {
    return szText;
}

int String::fGetLen() {
    return iLength;
}

bool String::fCompareTo(char *strText) {
    if (strcmp(szText,strText) == (0)) {
        return true;
    } else {
        return false;
    }
}


When I call fSetString() after creating a valid instance of the class I get an Access Violation error. It appears to happen because I am altering the string pointer "szText". I wrote a small Test App:#include <stdio.h>
#include "StringClass.h"

int main()
{
    String sz_A_Name("Matt");
    char *sz_B_Name = "Matt";
    char *sz_C_Name = "John";
    char *szTemp = "";
   
    if (sz_A_Name.fCompareTo(sz_B_Name) == true) {
        printf("\"%s\" and \"%s\" are the same!\n", sz_A_Name.fGetText(), sz_B_Name);
    } else {
        printf("\aHouston. we have a problem!\n");
    }

    if (sz_A_Name.fCompareTo(sz_C_Name) == false) {
        printf("\"%s\" and \"%s\" are not the same!\n", sz_A_Name.fGetText(), sz_C_Name);
    } else {
        printf("\aHouston. we have a problem!\n");
    }

    printf("The name \"%s\" is %i characters long!\n", sz_A_Name.fGetText(), sz_A_Name.fGetLen());
    printf("Please enter a new name: ");
    scanf("%s", szTemp);
    sz_A_Name.fSetString(szTemp);
    printf("Your new name is: %s\n\n", sz_A_Name.fGetText());
    printf("Test completed successfully!\n\n");

    return 0;
}


The program crashes when inputting the new name for the string. I tried debugging it and as earlier mentioned, discovered it was an Access Violation. I think szText is being invalidated after calling the constructor because the data it is pointing to is allocated on the heap, whereas the data being passed to it is allocated on the stack. Is there anyway to force where the data being passed to the constructor is allocated, or can anyone suggest a good way to get around this?
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

OnlyMeat

The stl aready provides a string class, why re-invent the wheel? Apart from that your code is incredibly ugly.


#include <string>
#include <iostream>

using namespace std;

int main()
{
   string MyStringClass = "hello world";
   if ( MyStringClass == "hello world" )
         cout << "std::string's overloaded equality operator returned true" << endl;
     
   return 0;
}


Arta

#2
You're not allocating any memory to szTemp. You're creating a pointer to an empty string:


char *szTemp = "";


You need to allocate some memory, either on the stack:


char szTemp[255] = {0};


or on the heap:


char *szTemp = new char[255];


You should also bare in mind that your class doesn't do allocate any memory for the string - it just saves a pointer to the memory allocated by the caller of fSetString. This means that, for the duration of the use of your string class, the memory must remain valid. This will break:



void somefunction(String *str)
{
   char x[] = "123";
   str->fSetString(x);
   
   return;
}

int main(int, char**)
{
   String *str = new String();

   somefunction(str);
 
   // the string is now invalid - because x was declared in the scope of somefunction
}


To make it more robust, have your constructor call fSetString, and have fSetString allocate some memory into which you should copy strText. Make sure you free it in your (missing!) destructor.

Dyndrilliac

Thanks Arta, fixed :)
Quote"Matt" and "Matt" are the same!
"Matt" and "John" are not the same!
The name "Matt" is 4 characters long!
Please enter a new name: Joe
Your new name is: Joe
Please enter another new name: Dave
Your new name is: Dave

Test completed successfully!

Press any key to continue
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

OnlyMeat

Quote from: Arta[vL] on June 10, 2005, 01:44 PM
You're not allocating any memory to szTemp. You're creating a pointer to an empty string:


char *szTemp = "";


You need to allocate some memory, either on the stack:


char szTemp[255] = {0};


or on the heap:


char *szTemp = new char[255];


That is incorrect, using this notation allocates memory on the stack:-


char* buf = "";
char* buf2="hello";
cout << sizeof(*buf) << buf2 << endl;


For buf it allocates a zero length string with a terminator on the stack, and for buf2 it allocates 5 bytes for the string and a null terminator on the stack.



Arta

I am not incorrect. Go away. The examples you provide are also ways to allocate memory on the stack, they are not the only ways. As a matter of fact, they are worse ways: the example you provide is not safe if you intend to write to the string.

This is the second time you've incorrectly told me I'm wrong. A somewhat essential prerequisite for being a smartass know-it-all is to actually know what you're talking about.

OnlyMeat

#6
Quote from: Arta[vL] on June 10, 2005, 06:11 PM
I am not incorrect. Go away.

Ok, lets clarify this shall we.

Quote from: Arta[vL] on June 10, 2005, 01:44 PM
You're not allocating any memory to szTemp. You're creating a pointer to an empty string:


char *szTemp = "";


Seems clear to me you are saying the code snippet above doesn't allocate any memory. This is incorrect, if you don't believe me run the code in my reply, you will find the size of the variable buf == 1 (the null terminator). This is clearly allocating 1 byte on the stack giving you a valid zero length string:-


char* buf = "";
char* buf2="hello";
cout << sizeof(*buf) << buf2 << endl;


I didn't think this forum was in the habit of pedaling false information. Am i wrong?.

Quote from: Arta[vL] on June 10, 2005, 06:11 PM
This is the second time you've incorrectly told me I'm wrong. A somewhat essential prerequisite for being a smartass know-it-all is to actually know what you're talking about.

If someone relays incorrect information then i will attempt to correct it. If you don't like it, then i have a simple solution, don't post it in the first place. Bitching at someone simply because they correct your mistakes demonstrates weak character.

I'm certainly not a know-it-all and would never presume to be. I don't believe anyone person knows everything. We all need to be corrected at one time or another, im just trying to help you.

Arta

#7
Quote
That is incorrect, using this notation allocates memory on the stack:-

You didn't even mention that you were referring to the amount of memory allocated. You just said "That is incorrect".

Sure, an empty string consumes a byte for the null terminator. What's that got to do with anything? I was trying to express that he's not allocating any memory for his temporary string, which he isn't, and that that was the cause of his problem, which it was. Then I showed him how to do it.

You can hardly expect people not to get irritated if you nit-pick at minutia.

Kp

Quote from: OnlyMeat on June 10, 2005, 08:48 PMThis is incorrect, if you don't believe me run the code in my reply, you will find the size of the variable buf == 1 (the null terminator). This is clearly allocating 1 byte on the stack giving you a valid zero length string:-char* buf = "";
char* buf2="hello";
cout << sizeof(*buf) << buf2 << endl;

Too bad this is also incorrect. :)  In most modern compilers, string constants can (and should!) be allocated read-only, which means the null terminator is going into a .rdata section, not on the stack.  Given that, you're consuming 4 bytes on the stack for the pointer to the null (ok, 8 bytes if it's a 64bit architecture).  buf2 also consumes a word's worth of space on the stack, defering the actual string content to .rdata.  Of course, given that you still use a C++ front-end that has to translate to C code first, it's understandable your remarks are a bit outdated (such as believing that string constants are put in writable memory).  Finally, using sizeof(*buf) there is a bit silly if you're trying to prove how much space buf consumes.  buf consumes 1 word for the pointer, and 1 byte for the null terminator.  sizeof(*buf) is equivalent to sizeof(char), since *buf is a char.  sizeof(char) is 1 on every system I've ever seen, so it doesn't matter what you point buf at - you'll still get 1 for that sizeof.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

OnlyMeat

Quote from: Kp on June 10, 2005, 10:00 PM
Too bad this is also incorrect.

Say what you like but the point is buf points to 1 byte of memory. You just agreed with that thanks :).

Dyndrilliac

Quote from: OnlyMeat on June 10, 2005, 11:24 PM
Quote from: Kp on June 10, 2005, 10:00 PM
Too bad this is also incorrect.

Say what you like but the point is buf points to 1 byte of memory. You just agreed with that thanks :).

Didn't you read what he said? Buf uses 5 bytes, not 1. 4 for the pointer itself, and 1 for the actual data. Also, it isn't on the stack.
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

OnlyMeat

Quote from: Dyndrilliac on June 11, 2005, 12:01 AM
Didn't you read what he said? Buf uses 5 bytes, not 1. 4 for the pointer itself, and 1 for the actual data. Also, it isn't on the stack.

Do you even know what a pointer is? clearly you don't. A pointer, points to a location in memory. buf is defined as a pointer to a zero length string with a null terminator. Therefore the size of the data it points to is 1 byte.

It seems you can't read or program because you obviously could not understand my previous post to reply in such a way. Here is it again for you:-

Quote from: OnlyMeat on June 10, 2005, 11:24 PM
Say what you like but the point is buf points to 1 byte of memory. You just agreed with that thanks :).

Kp is correct that the location is not on the stack. It has a static lifetime, however it must still be allocated and loaded into memory at runtime. Which proves the point that the variable buf will point to 1 byte of data. It doesn't matter if it's on the stack or allocated when the program starts statically it will be allocated in memory.

Dyndrilliac

Quote from: OnlyMeat on June 10, 2005, 03:57 PMThat is incorrect, using this notation allocates memory on the stack:-[/b

You're still incorrect in either case. And yes, I am aware of what a pointer is. When you said point to I took that to mean, the program itself refers to it (*buf) as 1 byte, which is not the case.
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

OnlyMeat

Quote from: Dyndrilliac on June 11, 2005, 02:07 AM
You're still incorrect in either case. And yes, I am aware of what a pointer is. When you said point to I took that to mean, the program itself refers to it (*buf) as 1 byte, which is not the case.

You still don't understand do you?
The point is it allocates memory for that null terminated string, it doesn't matter if it's allocated on the stack heap/free store or statically when the program starts, it's still allocated.

Arta originally said no allocation occurs, and my point stands that this is not true. If you don't understand the posts don't bother replying as you simply embarrass yourself by making dumb remarks.


Dyndrilliac

#14
Quote from: OnlyMeat on June 11, 2005, 03:16 AM
Quote from: Dyndrilliac on June 11, 2005, 02:07 AM
You're still incorrect in either case. And yes, I am aware of what a pointer is. When you said point to I took that to mean, the program itself refers to it (*buf) as 1 byte, which is not the case.

You still don't understand do you?
The point is it allocates memory for that null terminated string, it doesn't matter if it's allocated on the stack heap/free store or statically when the program starts, it's still allocated.

Arta originally said no allocation occurs, and my point stands that this is not true. If you don't understand the posts don't bother replying as you simply embarrass yourself by making dumb remarks.



I understand the posts perfectly fine you arrogant pretentious prick. I never said anything regarding Arta's post. I was simply saying that taking away everything else in this thread but YOUR original post, you ALSO posted something that is WRONG. If you have to insult other people with your stubborn fantasy world where noone is correct but you to get over the fact that within the last week you have been WRONG on several occasions then so be it but don't be surprised when more people get sick of seeing your crap and you find yourself banned.

Your problem is you can't politely interject in the conversation - everyone already in it has got to either be wrong or ignorant otherwise the the threads of the universe cave in on themselves and existence negates itself.

Edit: Oh, and one one more think I would like to point out. Arta's response was helpful, and is the reason my program works now - yours on the other hand was not. You said nothing helpful whatsoever, which makes me ponder, whats the purpose of you posting in this thread at all?
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.