Problems with pointers.

M

Magnus Malm

Hello

I am not quite sure if this is the right place to post this question, but I
hope this group is one of the rare ones that forgive less wise ones like
me. :)

I have quite a hard time trying to figure out what I am doing wrong.
Pointers are involved, and structures, and functions taking pointers as
parameters and returning pointers. It's one big pointer mess really.

I am coding and compiling under Win98 (MS-DOS) using DJGPP, GCC version
3.22 with the -g switch (though debugging won't work :(). The machine is an
AMD Athlon 1.2GHz, 512MB SDRAM. Hope I diden't miss any important specs.

Now to the problem at hand. I successfully manage to compile the following
program:

typedef struct {
char *name;
char *msg;
char *desc;
} testt;

testt *init_test(testt *test, char *name, char *msg, char *desc);

int main (int argc, char **argv){
testt *test;

test = init_test(test, "Test name", "Test msg", "Test desc");

free(test->name);
free(test->msg);
free(test->desc);
free(test);

return 0;
}

testt *init_test(testt *test, char *name, char *msg, char *desc){

test = (testt *)malloc(sizeof(testt *));

test->name = malloc(sizeof(char) * (strlen(name)));
test->msg = malloc(sizeof(char) * (strlen(msg)));
test->desc = malloc(sizeof(char) * (strlen(desc)));

strcpy(test->name, name);
strcpy(test->msg, msg);
strcpy(test->desc, desc);

return test;
}

Obviously, this is no real program, only the basic principle that I use in
the real project. When I run this program, it crashes with the following
ouput:

Exiting due to signal SIGSEGV
General Protection Fault at eip=000036d5
eax=ffffffd4 ebx=ffffffcc ecx=ffffffcc edx=00000000 esi=0008dda4
edi=ffffffd4
ebp=0008d938 esp=0008d92c
program=F:\CODING\PROJECTS\C\TW\CORE\TEST\PROBE.EXE
cs: sel=00a7 base=83ed2000 limit=0009ffff
ds: sel=00b7 base=83ed2000 limit=0009ffff
es: sel=00b7 base=83ed2000 limit=0009ffff
fs: sel=0087 base=00019190 limit=0000ffff
gs: sel=00c7 base=00000000 limit=0010ffff
ss: sel=00b7 base=83ed2000 limit=0009ffff
App stack: [0008d978..0000d978] Exceptn stack: [0000d8d8..0000b998]

Call frame traceback EIPs:
0x000036d5
0x00001727
0x00003068

I am guessing that it has something to do with illegal memory access or the
like. But that is just a guess.

I really hope someone have the kindness to shed some light on this problem.
Because I am clueless.

Many thanks in advance.

/Locke
 
J

Joona I Palaste

Magnus Malm said:
I am not quite sure if this is the right place to post this question, but I
hope this group is one of the rare ones that forgive less wise ones like
me. :)
I have quite a hard time trying to figure out what I am doing wrong.
Pointers are involved, and structures, and functions taking pointers as
parameters and returning pointers. It's one big pointer mess really.
I am coding and compiling under Win98 (MS-DOS) using DJGPP, GCC version
3.22 with the -g switch (though debugging won't work :(). The machine is an
AMD Athlon 1.2GHz, 512MB SDRAM. Hope I diden't miss any important specs.
Now to the problem at hand. I successfully manage to compile the following
program:
typedef struct {
char *name;
char *msg;
char *desc;
} testt;
testt *init_test(testt *test, char *name, char *msg, char *desc);
int main (int argc, char **argv){
testt *test;
test = init_test(test, "Test name", "Test msg", "Test desc");

return 0;
}
testt *init_test(testt *test, char *name, char *msg, char *desc){
test = (testt *)malloc(sizeof(testt *));

Lose the cast, it's useless. Here's a better version:
test = malloc(sizeof *test);
test->name = malloc(sizeof(char) * (strlen(name)));
test->msg = malloc(sizeof(char) * (strlen(msg)));
test->desc = malloc(sizeof(char) * (strlen(desc)));

Lose the casts. Also sizeof(char) is always 1, so multiplying by it is
superfluous.
strcpy(test->name, name);
strcpy(test->msg, msg);
strcpy(test->desc, desc);

The problem here is that strlen() does not count the null terminator,
but strcpy() tries to copy it anyway. You have to add it yourself to
the length:
test->name = malloc(strlen(name)+1);
test->msg = malloc(strlen(msg)+1);
test->desc = malloc(strlen(desc)+1);
return test;
}
Obviously, this is no real program, only the basic principle that I use in
the real project. When I run this program, it crashes with the following
ouput:

(snip Windows-specific stuff)
I am guessing that it has something to do with illegal memory access or the
like. But that is just a guess.

It's an illegal memory access. strcpy() is poking its nose where it does
not belong. You did not allocate enough memory for it to poke its nose
to.
I really hope someone have the kindness to shed some light on this problem.
Because I am clueless.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"You have moved your mouse, for these changes to take effect you must shut down
and restart your computer. Do you want to restart your computer now?"
- Karri Kalpio
 
B

Blah

Joona I Palaste said:
Lose the cast, it's useless. Here's a better version:
test = malloc(sizeof *test);

While the other (snipped) corrections were necessary, I think this line
in the uncorrected version was the most likely cause of the seg fault, as
the original call to malloc has sizeof(testt *) rather than sizeof(testt)

Joona didn't just improve the clarity of the code, he removed a bug as
well.
 
A

Al Bowers

Magnus said:
Now to the problem at hand. I successfully manage to compile the following
program:

typedef struct {
char *name;
char *msg;
char *desc;
} testt;

testt *init_test(testt *test, char *name, char *msg, char *desc);

int main (int argc, char **argv){
testt *test;

test = init_test(test, "Test name", "Test msg", "Test desc");

free(test->name);
free(test->msg);
free(test->desc);
free(test);

return 0;
}

testt *init_test(testt *test, char *name, char *msg, char *desc){

test = (testt *)malloc(sizeof(testt *));

test->name = malloc(sizeof(char) * (strlen(name)));
test->msg = malloc(sizeof(char) * (strlen(msg)));
test->desc = malloc(sizeof(char) * (strlen(desc)));

strcpy(test->name, name);
strcpy(test->msg, msg);
strcpy(test->desc, desc);

return test;
}

You should redesign the function init_test. malloc of a struct
is probably not neccessary. Remember, all dynamic allocations
have the potential of failure. You should always test the return
value of the allocating function (malloc in this code). In addition,
you have not allocated enough space to hold the string literal
arguments.

A redesigned example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct testt
{
char *name;
char *msg;
char *desc;
}testt;

testt *init_test(testt *test, const char *name,
const char *msg, const char *desc);
void freeALL(testt *test);

int main (void)
{
testt test = {NULL,NULL,NULL}; /* Neccessary initialization */

if(init_test(&test, "Test name", "Test msg", "Test desc") == NULL)
puts("Failure in allocations");
else printf("test.name = \"%s\"\ntest.msg = \"%s\"\n"
"test.desc = \"%s\"\n",test.name,test.msg,test.desc);
freeALL(&test);
return 0;
}

testt *init_test(testt *test, const char *name,
const char *msg, const char *desc)
{
if((test->name = malloc(strlen(name)+1)) == NULL)
{
freeALL(test);
return NULL;
}
if((test->msg = malloc(strlen(msg)+1)) == NULL)
{
freeALL(test);
return NULL;
}
if((test->desc = malloc(strlen(desc)+1)) == NULL)
{
freeALL(test);
return NULL;
}
strcpy(test->name, name);
strcpy(test->msg, msg);
strcpy(test->desc, desc);
return test;
}

void freeALL(testt *test)
{
free(test->name);
free(test->msg);
free(test->desc);
test->name = test->msg = test->desc = NULL;
return;
}
 
S

Samuel Barber

Joona I Palaste said:
Lose the cast, it's useless. Here's a better version:
test = malloc(sizeof *test);

The cast is harmless, but the size is wrong. sizeof(testt *) is the
size of a pointer. sizeof(testt) is the size of the struct.

Yes. Get a debugger.

Sam
 
R

Richard Bos

The cast is harmless,

Actually, since the OP forgot to

#include <stdlib.h>

the cast isn't harmless at all. If it hadn't been there, he would've
been warned that he forgot to include a proper declaration of malloc().
but the size is wrong.

That, as well.

Richard
 
G

goose

Magnus Malm said:
Hello

I am not quite sure if this is the right place to post this question, but I
hope this group is one of the rare ones that forgive less wise ones like
me. :)

I have quite a hard time trying to figure out what I am doing wrong.
Pointers are involved, and structures, and functions taking pointers as
parameters and returning pointers. It's one big pointer mess really.

I am coding and compiling under Win98 (MS-DOS) using DJGPP, GCC version
3.22 with the -g switch (though debugging won't work :(). The machine is an
AMD Athlon 1.2GHz, 512MB SDRAM. Hope I diden't miss any important specs.

Now to the problem at hand. I successfully manage to compile the following
program:

typedef struct {
char *name;
char *msg;
char *desc;
} testt;

testt *init_test(testt *test, char *name, char *msg, char *desc);

int main (int argc, char **argv){
testt *test;

test = init_test(test, "Test name", "Test msg", "Test desc");

free(test->name);
free(test->msg);
free(test->desc);
free(test);

return 0;
}

testt *init_test(testt *test, char *name, char *msg, char *desc){

test = (testt *)malloc(sizeof(testt *));

1. there is no need for the cast. in fact, it would help you
if you left it out.
2. you are allocating enough memory to store a *pointer* to
testt, not enough memory to store an object of testt.
test->name = malloc(sizeof(char) * (strlen(name)));

remember that strlen() returns the number of characters
in the string. e.g.
char *s = "12345";
printf ("%u\n", strlen(s)); /* prints out 5 */

you allocate enough memory to store all the characters
in the string, but not enough to store the terminator '\0'.

do the following:
test->name = malloc (strlen (name) + 1);
test->msg = malloc(sizeof(char) * (strlen(msg)));
test->desc = malloc(sizeof(char) * (strlen(desc)));

strcpy(test->name, name);
strcpy(test->msg, msg);
strcpy(test->desc, desc);

return test;
}

<snipped>

hth
goose,
 
K

Kevin Easton

Magnus Malm said:
int main (int argc, char **argv){
testt *test;

test = init_test(test, "Test name", "Test msg", "Test desc");

In addition to the errors that others have pointed out, you're passing
the value of an uninitialised variable here ("test"). You could
initialise test:

testt *test = NULL;

or just remove that parameter entirely - it's not needed, you overwrite
its value immediately in the function anyway, so you might as well just
have a local variable.

- Kevin.
 
M

Magnus Malm

The cast is harmless, but the size is wrong. sizeof(testt *) is the
size of a pointer. sizeof(testt) is the size of the struct.

This was the *big* bad error. The minor one was that I forgot to allocate
strlen(name) + 1. All corrected now and it works like a charm.
Yes. Get a debugger.

As you might have read in my original post, the debugger doesn't work even
though I have the switch -g on (in DJGPP). Sure, I could run the debugger
used by DJGPP, outside the editor. Guess I don't like the idea of exiting
the editor, running the debugger, return back to the editor, etc. when
there should be a feature to use the debugger straight from the editor. Oh
well, that's a different story entirly.

Thanks for all the help from all. Cheers

/Locke
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top