Archived

This topic is now archived and is closed to further replies.

I need help with this please

This topic is 5668 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

okay, i am doing a chapter in a book on C++ to help me understand pointers (AK!) and i did one of the sample problems. the problem is that one of the variables is acting up...
void main() {
	char *str = "I'm afraid I can't let you do that Dave.";
	char *ch = &str[0];

	for (unsigned int i = 0; i
this is what the book gives, but when i ran it, i get a general protection fault. After an hour of trying different things, i got it work by defining
       char *str = "I'm afraid I can't let you do that Dave.";  
as
       char str[] = "I'm afriad I can't let you do that Dave.";    
It works and everything, i am just curious as to what happened. Why did the first declartion not work? I have other examples, where defining a string like that worked, but here it f'ed up. Thanks in advance, Jon ''Can I go back?'' ''No. But if you could, would you really want to?'' - mr. neo [edited by - mtrneo3 on June 5, 2002 4:36:34 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
be carefully working with strings and pointers...
when u declare char str[] = "blabla...";
your compiler put by itself the END OF STRING, i mean the carcter NULL or ''\0'';
when u declare char *str = "blabla..."; that doesn''t happen..
So your function strlen(char *); CAN''T find how big is your string... (it counts untill find NULL). when you try to use *s or *e will occur an error: u are trying to acess a NOT ALLOCED MEMORY!

i hope u understand...

Share this post


Link to post
Share on other sites
That''s completely false.

At least in vc++

I just tested and compiled this code:


  
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc,char** argv)
{
char* blah = "This is a test.";
cout << strlen(blah) << endl;
return 0;
}


Works flawlessly.

Share this post


Link to post
Share on other sites
akiinao: ch and str point to the same memory location after the initial assignment, and strlen will most definitely work with any one of them.

mtrneo3: The only explanation I can think of is this. When you declare str as ''char *str'', str is a pointer that points to a string that is stored in constant segment. Since you don''t have write access to constant memory, you get access violation when you''re trying to change str. With the second declaration, however, actual memory is allocated for str and that memory is initialized with your string. This memory is writeable, and your program runs fine. Your first declaration should be ''const char *str'' to indicate that the pointer points to constant memory.

I suppose that with proper optimizations,

const char *str1 = "Some string";
const char *str2 = "Some string";

will point to the same memory location, since "Some string" is assumed to be constant. This may lead to serious problems if you''re trying to modify data pointed to by either str1 or str2. However, in this case:

char str1[] = "Some string";
char str2[] = "Some string";

str1 and str2 will point to different memory areas, and each one will have its own copy of "Some string."

Also, your for loop:

for (unsigned int i = 0; i<strlen(str); i++)

is better replaced with this while loop:

while (*ch)

Share this post


Link to post
Share on other sites
Unfortunately I too have encountered this prob before. The problem lies in the windows api header and library files -- more recent versions don''t support that modifying of pointers and stuff, like the older versions do. I would guess that the book you''re using is an obsolete dinosaur (translation:2-5 years old) , so just follow IndirectX''s instructions and you should be fine.

Twilight Dragon
www.freewebz.com/j-world

Share this post


Link to post
Share on other sites
quote:
Original post by TDragon
The problem lies in the windows api header and library files -- more recent versions don''t support that modifying of pointers and stuff, like the older versions do.

If anything, the "problem" is in stricter memory access permissions, which should depend on the compiler and the runtime operating system.

Share this post


Link to post
Share on other sites
thanx alot... I think I actually understand some of these replies (wow...)

Indirectx - so what ur saying is that since *str = "bla" only points to the memory location at which the string begins (constant memory?), it actually dosen''t refer to a ''string'' but only three chars located somewhere in memory... did I get that right?

I think I am getting a handle on these things... now just to figure them out without a book

thanks alot guys



''''Can I go back?''''
''''No. But if you could, would you really want to?''''

- mr. neo

Share this post


Link to post
Share on other sites
Imagine you have two types of memory: constant segment and data segment. When you are referring to a string literal, such as

printf("This is a string literal\n");

that string literal is put into the constant segment. When you are using a variable, such as

int var;
char anotherVar;
char yetAnotherVar[1000];

all of these are put into the data segment. You can only read constant segment, and you have full access to the write segment. Now, if you declare a string pointer like so:

const char *string_ptr = "A string stored in a constant segment";

then four bytes (size of a pointer) are allocated for string_ptr, the variable string_ptr itself is stored in the data segment, and it points to a string that is stored in a constant segment. However, if you declare a char array like so:

char string[] = "This string is stored in data segment";

then string has the sizeof equal to strlen(string)+1, meaning memory in data segment is allocated for the entire string, not just for a 4-byte pointer, and the whole string is copied to that allocated space. Here's my pathetic attempt to graphically represent what I'm talking about:


Takes a while to get the image tags right!

[edited by - IndirectX on June 5, 2002 11:42:10 PM]

Share this post


Link to post
Share on other sites
This is a little long and doesn't add much, I was just interested and played with it, it would appear that (gcc at least) actually puts both strings into the code segment and then copies the string into the stack to use it, however when dealing with a pointer, it will then go back and attempt to actually modify the pointed to memory (ie in the code segment) - crashing the program, whereas when dealing with the array version it will actually modify the stack.

(asm is in AT&T syntax, operands are reversed from intel and (%eax) means [eax], the rest is hopefully easyish to pick up). No optimizations are on.


      
int main(int argc,char** argv)
{
const char* str1 = "Hello, world";
char str2[] = "Hello again, world";



}



gives



gcc2_compiled.:
___gnu_compiled_c:
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "Hello, world\0"
LC1:
.ascii "Hello again, world\0"
.align 4
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp,%ebp
subl $64,%esp
pushl %edi
pushl %esi
call ___main
movl $LC0,-4(%ebp)
leal -48(%ebp),%eax
leal -48(%ebp),%edi
movl $LC1,%esi
cld
movl $4,%ecx
rep
movsl
movsw
movsb
L2:
leal -72(%ebp),%esp
popl %esi
popl %edi
leave
ret


Note the two strings are defined in the code (text) segment, does exactly the same without the const qualifier.

Then, trying to modify these:


        
int main(int argc,char** argv)
{
char* str1 = "Hello, world";
char str2[] = "Hello again, world";


str1[0] = 'J';

}


Crashes, asm source


.file "str1.c"
gcc2_compiled.:
___gnu_compiled_c:
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "Hello, world\0"
LC1:
.ascii "Hello again, world\0"
.align 4
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp,%ebp
subl $64,%esp
pushl %edi
pushl %esi
call ___main
movl $LC0,-4(%ebp)
leal -48(%ebp),%eax
leal -48(%ebp),%edi
movl $LC1,%esi
cld
movl $4,%ecx
rep
movsl
movsw
movsb
movl -4(%ebp),%eax
movb $74,(%eax) # eax points to string (pointer is stored on stack at [ebp - 4] earlier)
L2:
leal -72(%ebp),%esp
popl %esi
popl %edi
leave
ret


And attempting to modify str2:


  
int main(int argc,char** argv)
{
char* str1 = "Hello, world";
char str2[] = "Hello again, world";


str2[0] = 'J';

}


Asm:


.file "str1.c"
gcc2_compiled.:
___gnu_compiled_c:
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "Hello, world\0"
LC1:
.ascii "Hello again, world\0"
.align 4
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp,%ebp
subl $64,%esp
pushl %edi
pushl %esi
call ___main
movl $LC0,-4(%ebp)
leal -48(%ebp),%eax
leal -48(%ebp),%edi
movl $LC1,%esi
cld
movl $4,%ecx
rep
movsl
movsw
movsb
movb $74,-48(%ebp)
L2:
leal -72(%ebp),%esp
popl %esi
popl %edi
leave
ret


EDIT: tags

[edited by - JuNC on June 9, 2002 9:53:47 AM]

Share this post


Link to post
Share on other sites