Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
I didn't think I was *this* bad with pointers.... [solved]
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
poly_poly-man
Advocate
Advocate


Joined: 06 Dec 2006
Posts: 2477
Location: RIT, NY, US

PostPosted: Sun Jun 08, 2008 2:31 am    Post subject: I didn't think I was *this* bad with pointers.... [solved] Reply with quote

Okay, have fun.

this works:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

int main() {
   printf("test1\n");
   FILE *myfd = fopen("/etc/mtab", "r");
   printf("test2 %i\n", myfd);
   char *pizza;
   //char **great_pizza;
   printf("goo\n");
   while (fgets(pizza, 1024, myfd)) {
      printf("boo\n");
      printf("%s\n", pizza);
      sleep(1);
   }
   fclose(myfd);
   printf("closed\n");
   return 0;
}


this doesn't:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

int main() {
   printf("test1\n");
   FILE *myfd = fopen("/etc/mtab", "r");
   printf("test2 %i\n", myfd);
   char *pizza;
   char **great_pizza;
   printf("goo\n");
   while (fgets(pizza, 1024, myfd)) {
      printf("boo\n");
      printf("%s\n", pizza);
      sleep(1);
   }
   fclose(myfd);
   printf("closed\n");
   return 0;
}


I need that char ** for later....

btw, the second one's last output is goo then it segfaults.

why is this happening?

poly-p man
_________________
iVBORw0KGgoAAAANSUhEUgAAA

avatar: new version of logo - see topic 838248. Potentially still a WiP.


Last edited by poly_poly-man on Sun Jun 08, 2008 4:32 pm; edited 1 time in total
Back to top
View user's profile Send private message
alkan
Guru
Guru


Joined: 06 Aug 2004
Posts: 385
Location: kasimlar yaylasi

PostPosted: Sun Jun 08, 2008 2:43 am    Post subject: Reply with quote

for both, you need to allocate memory for pizza and great_pizza. Even though first one works, it is still not right to write into those pointers without first allocating memory. man malloc.
Back to top
View user's profile Send private message
avendesora
Veteran
Veteran


Joined: 16 Aug 2002
Posts: 1739
Location: Betelgeuse vicinity

PostPosted: Sun Jun 08, 2008 9:03 am    Post subject: Reply with quote

Also you second printf is wrong, %i is not appropriate for a pointer - you'll get
strange bugs on different plateforms (sizeof(int) != sizeof(void*) is rather common).

And you need to include something to get sleep(). Not having the right prototypes can
also lead to strange stuff too.

So compile with -Wall and save yourself some painful debugging later on :-)
Back to top
View user's profile Send private message
poly_poly-man
Advocate
Advocate


Joined: 06 Dec 2006
Posts: 2477
Location: RIT, NY, US

PostPosted: Sun Jun 08, 2008 11:07 am    Post subject: Reply with quote

thanks for the tip with malloc - I actually have never used it before :D


Also, that was a temporary printf I threw in (the one printing th file descriptor) because a previous version of the program kept giving my null file descriptors (Can you really not fopen() /proc/mounts?)

I will compile with -Wall from now on - it does make sense to avoid every errror (this code will eventually be merged into the rest of my init system).

poly-p man

(the main code includes the right file for sleep - I just forgot to here)
_________________
iVBORw0KGgoAAAANSUhEUgAAA

avatar: new version of logo - see topic 838248. Potentially still a WiP.
Back to top
View user's profile Send private message
poly_poly-man
Advocate
Advocate


Joined: 06 Dec 2006
Posts: 2477
Location: RIT, NY, US

PostPosted: Sun Jun 08, 2008 2:02 pm    Post subject: Reply with quote

Ran this code past my dad (he programs for a living, albeit in c++), and he found the same mistake you did...

so, if I malloc() pizza, I can do great_pizza without malloc(). However, he says before I actually *use* it, I should malloc() it as well.

How do I malloc() a char **? How do I *free* a char**?

poly-p man
_________________
iVBORw0KGgoAAAANSUhEUgAAA

avatar: new version of logo - see topic 838248. Potentially still a WiP.
Back to top
View user's profile Send private message
alkan
Guru
Guru


Joined: 06 Aug 2004
Posts: 385
Location: kasimlar yaylasi

PostPosted: Sun Jun 08, 2008 3:36 pm    Post subject: Reply with quote

been a while since i programmed in c, (recently involved more with c++,python), one way might be something like this:
Code:

   int i;
        char **c;
        c = (char**)malloc(10*sizeof(char*));
        for(i=0; i<10; i++){
                c[i] = (char*)malloc(sizeof(char));
        }

        for(i=0; i <10; i++){
                free(c[i]);
        free(c);


Edit: I allocated 1 char size in the loop, but you can put any size you want, depending on how long a string you want to hold in it ( c[i]=(char*)malloc(1024*sizeof(char)) )
Back to top
View user's profile Send private message
Lightangel
Tux's lil' helper
Tux's lil' helper


Joined: 10 Jul 2007
Posts: 127

PostPosted: Sun Jun 08, 2008 4:00 pm    Post subject: Reply with quote

Also malloc can be replaced with calloc (it has the same syntax)
when you want to have allocated space without any trash values.
It is useful ;).
Back to top
View user's profile Send private message
Hu
Watchman
Watchman


Joined: 06 Mar 2007
Posts: 9168

PostPosted: Sun Jun 08, 2008 4:22 pm    Post subject: Reply with quote

If you encounter crashes with warning free code, you should run the program under dev-util/valgrind. When you use the memcheck tool, it can detect use of uninitialized values and use after free bugs, both of which are very serious mistakes that can sometimes be hard to spot from code inspection.
Back to top
View user's profile Send private message
poly_poly-man
Advocate
Advocate


Joined: 06 Dec 2006
Posts: 2477
Location: RIT, NY, US

PostPosted: Sun Jun 08, 2008 4:32 pm    Post subject: Reply with quote

Hu wrote:
If you encounter crashes with warning free code, you should run the program under dev-util/valgrind. When you use the memcheck tool, it can detect use of uninitialized values and use after free bugs, both of which are very serious mistakes that can sometimes be hard to spot from code inspection.


can I do the same with gdb? I don't want to compile valgrind (keep in mind I'm on a 486 - not gentoo :D )...

@alkan: thanks for the tip, it's working fine. Got me my strcpy, and it's coming along fine.

poly-p man
_________________
iVBORw0KGgoAAAANSUhEUgAAA

avatar: new version of logo - see topic 838248. Potentially still a WiP.
Back to top
View user's profile Send private message
Mad Merlin
Veteran
Veteran


Joined: 09 May 2005
Posts: 1143

PostPosted: Mon Jun 09, 2008 12:15 am    Post subject: Reply with quote

poly_poly-man wrote:
Hu wrote:
If you encounter crashes with warning free code, you should run the program under dev-util/valgrind. When you use the memcheck tool, it can detect use of uninitialized values and use after free bugs, both of which are very serious mistakes that can sometimes be hard to spot from code inspection.


can I do the same with gdb? I don't want to compile valgrind (keep in mind I'm on a 486 - not gentoo :D )...


No, Valgrind is a very different tool than gdb. Valgrind is also your friend (moreso than gdb).

Have a look: (broken.c contains your "working" program)
Code:

$ gcc -g3 broken.c -o broken
$ valgrind ./broken
==28779== Memcheck, a memory error detector.
==28779== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==28779== Using LibVEX rev 1804, a library for dynamic binary translation.
==28779== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==28779== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==28779== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==28779== For more details, rerun with: -v
==28779==
test1
test2 83243056
goo
==28779== Use of uninitialised value of size 8
==28779==    at 0x4D858C5: _IO_getline_info (in /lib64/libc-2.5.so)
==28779==    by 0x4D846BE: fgets (in /lib64/libc-2.5.so)
==28779==    by 0x4006FF: main (broken.c:13)
==28779==
==28779== Invalid write of size 1
==28779==    at 0x4D858C5: _IO_getline_info (in /lib64/libc-2.5.so)
==28779==    by 0x4D846BE: fgets (in /lib64/libc-2.5.so)
==28779==    by 0x4006FF: main (broken.c:13)
==28779==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28779==
==28779== Process terminating with default action of signal 11 (SIGSEGV)
==28779==  Access not within mapped region at address 0x0
==28779==    at 0x4D858C5: _IO_getline_info (in /lib64/libc-2.5.so)
==28779==    by 0x4D846BE: fgets (in /lib64/libc-2.5.so)
==28779==    by 0x4006FF: main (broken.c:13)
==28779==
==28779== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 5 from 1)
==28779== malloc/free: in use at exit: 568 bytes in 1 blocks.
==28779== malloc/free: 1 allocs, 0 frees, 568 bytes allocated.
==28779== For counts of detected errors, rerun with: -v
==28779== searching for pointers to 1 not-freed blocks.
==28779== checked 75,096 bytes.
==28779==
==28779== LEAK SUMMARY:
==28779==    definitely lost: 0 bytes in 0 blocks.
==28779==      possibly lost: 0 bytes in 0 blocks.
==28779==    still reachable: 568 bytes in 1 blocks.
==28779==         suppressed: 0 bytes in 0 blocks.
==28779== Rerun with --leak-check=full to see details of leaked memory.
Segmentation fault

_________________
Game! - Where the stick is mightier than the sword!
Back to top
View user's profile Send private message
Hu
Watchman
Watchman


Joined: 06 Mar 2007
Posts: 9168

PostPosted: Tue Jun 10, 2008 3:14 am    Post subject: Reply with quote

You could build Valgrind on a Gentoo system and copy over the relevant files to the 486. However, the performance will leave a lot to be desired. Although Valgrind is very thorough, that thoroughness comes at a substantial cost in speed and size. A program run under supervision by Valgrind will be much slower and larger than its unsupervised counterpart. I doubt a 486 could give acceptable performance for a program under control of Valgrind.
Back to top
View user's profile Send private message
Akkara
Administrator
Administrator


Joined: 28 Mar 2006
Posts: 5323
Location: &akkara

PostPosted: Tue Jun 10, 2008 7:25 am    Post subject: Reply with quote

I see this has been mostly answered already, but I'd like to add some thoughts to it.

The kinds of bugs you are finding is, unfortunately, *very* easy to make especially as one first starts using pointers in more interesting ways.

None of your pointers are initialized. This means they could point to anywhere. Usually this is a invalid address which gives a segmentation error. Consider yourself lucky when you see one: it means there's a pointer problem that you need to find. The alternative - that the program works anyway - is much worse, because there's still a latent bug in it but you are left unaware of it.

The advice many have offered, of using -Wall, and valgrind, is *very* good advice. If the machine you intend to run this under is too slow or too small to have a rich environment, try to run as much of the code as you can on a more modern system that does support valgrind. Turn off any functionality you don't want activated, or that isn't supported on your main box (define a "PRETEND" macro and use ifdef's or something like that), and run the rest of it with valgrind. It'll save a ton of headaches later. It'll also slowly teach what the troublesome areas tend to look like, and over time you'll know instinctively to avoid them.

The reason that code sometimes (even often) works even though pointers haven't been initialized, is that the libraries use pointers extensively. When a function exits, many of the CPU registers are still holding whatever values the function had as it did its thing. If one of your uninitialized pointers then happen to get assigned to one of those registers, it'll appear to work. Except it'll be stomping over data that's important to that library. And next time you call that library you might be in for a surprise. (And if you never call the library again, you might even never know ... until N years down the road when someone comes along and wants to multi-thread the app, and suddenly all hell breaks loose.)
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum