• RSS
  • Twitter
  • FaceBook

Security Forums

Log in

FAQ | Search | Usergroups | Profile | Register | RSS | Posting Guidelines | Recent Posts

Using Malloc in C

Users browsing this topic:0 Security Fans, 0 Stealth Security Fans
Registered Security Fans: None
Post new topic   Reply to topic   Printer-friendly version    Networking/Security Forums Index -> Programming and More

View previous topic :: View next topic  
Author Message
MattA
Trusted SF Member
Trusted SF Member


Joined: 13 Jun 2003
Posts: 16777193
Location: Eastbourne + London

Offline

PostPosted: Mon Dec 19, 2005 3:44 pm    Post subject: Using Malloc in C Reply with quote

Is this the correct use of Malloc? It's just i noticed it works just as well without the string = malloc(5) section.

Code:

#include <stdio.h>
#include <stdlib.h>
char *string;
main ()
{
string = malloc(5);
char *string = "Matt";
printf("%s rocks!!\n",string);
return 0;
}
Back to top
View user's profile Send private message
hugo
Forum Fanatic
Forum Fanatic


Joined: 14 Jun 2003
Posts: 16777215
Location: Netherlands, Europe

Offline

PostPosted: Mon Dec 19, 2005 4:34 pm    Post subject: Re: Using Malloc in C Reply with quote

MattA wrote:
Is this the correct use of Malloc? It's just i noticed it works just as well without the string = malloc(5) section.

It's alright but there's a couple of things wrong with the code there. For instance you are refering to 2 char pointers called 'string'. That at least confuses me, maybe possible the compiler also (although the program worked as you said).

The string that is printed however, is not your allocated memory. That is gone.

You first did this:
Code:
string = malloc(5);

...which is OK, but later you do
Code:
char *string = "Matt";

There you are assigning a new variable 'string', where basically the compiler does some typecasting and actually does this:
the pointer that string points to shall be pointed to the address of the character of the string 'Matt'

Then,
Code:
printf("%s rocks!!\n",string);

prints said string, but the malloc( ) memory is gone, you have no reference to it anymore.

This code does use malloc( ) and update the contents:
Code:
char *string = malloc( 5 );
snprintf( string, 4, "%s", "Matt" );
printf( "%s rocks\n", string);
free( string );


Hope this helps. Smile
Back to top
View user's profile Send private message
MattA
Trusted SF Member
Trusted SF Member


Joined: 13 Jun 2003
Posts: 16777193
Location: Eastbourne + London

Offline

PostPosted: Mon Dec 19, 2005 10:04 pm    Post subject: Reply with quote

Cheers Hugo. Even threw in the free command to free up the memory too Wink
Back to top
View user's profile Send private message
capi
SF Senior Mod
SF Senior Mod


Joined: 21 Sep 2003
Posts: 16777097
Location: Portugal

Offline

PostPosted: Tue Dec 20, 2005 12:18 am    Post subject: Re: Using Malloc in C Reply with quote

hugo wrote:
There you are assigning a new variable 'string', where basically the compiler does some typecasting and actually does this:
the pointer that string points to shall be pointed to the address of the character of the string 'Matt'

Well, to be more accurate, it does: string shall be pointed to the address of the first character in the character array 'Matt'

Note that string (a pointer variable) is not pointing to a pointer, it is pointing to a character. To be pointing to a pointer (as in "the pointer that string points to") it would have to be a char **.

hugo wrote:
Then,
Code:
printf("%s rocks!!\n",string);

prints said string, but the malloc( ) memory is gone, you have no reference to it anymore.

I know you know this, but I'll say it to avoid anyone confusing matters: the malloc'ed memory is not gone; whether there are any references to it is irrelevant. The memory is still there, it is still being occupied (and could still be read if you had a pointer to it, or if you did a search of your memory space), and must still be freed. I say this mainly to avoid any sort of confusion by those who are accustomed to Java (spit spit) and other garbage-collected languages: memory you allocate is still there until you explicitly free it, regardless of whether there are any references to it or not.

hugo wrote:
Code:
char *string = malloc( 5 );
snprintf( string, 4, "%s", "Matt" );
printf( "%s rocks\n", string);
free( string );

Using s(n)printf to copy a string is a bit overkill, though... Razz A simple strcpy would do just fine Wink (no need for strncpy even, you know how many characters the "Matt" string has).
Back to top
View user's profile Send private message
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Tue Dec 20, 2005 3:43 pm    Post subject: Reply with quote

Going allong with the free, wich one of these two codes are more acurate?
Code:

char *tmp;
int i=0;
while(i<=3000){
  if((tmp=(char*)malloc(sizeof(char)*strlen("TEST")))==NULL){
    perror("malloc");
    exit(1);
  }
  bzero(tmp,strlen(temp));
  strncpy(tmp,"TEST",strlen("TEST");
  fprintf(stdout,"%s\n",tmp);
  free(tmp);
}

Or this:
Code:

char *tmp;
int i=0;
while(i<=3000){
  if((tmp=(char*)malloc(sizeof(char)*strlen("TEST")))==NULL){
    perror("malloc");
    exit(1);
  }
  bzero(tmp,strlen(temp));
  strncpy(tmp,"TEST",strlen("TEST");
  fprintf(stdout,"%s\n",tmp);
}
free(tmp);


Where should I put the free?On the first one, after It runs a couple of time, it throws me an invalid free pointer error, and the other works fine, but shouldn't i use realloc instead of malloc for the second version???

Thanks a lot.

Zarnick
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Sysop_fb
Just Arrived
Just Arrived


Joined: 27 Sep 2005
Posts: 0
Location: Iraq for the moment

Offline

PostPosted: Tue Dec 20, 2005 4:44 pm    Post subject: Reply with quote

Zarnick wrote:
Going allong with the free, wich one of these two codes are more acurate?
Code:

char *tmp;
int i=0;
while(i<=3000){
  if((tmp=(char*)malloc(sizeof(char)*strlen("TEST")))==NULL){
    perror("malloc");
    exit(1);
  }
  bzero(tmp,strlen(temp));
  strncpy(tmp,"TEST",strlen("TEST");
  fprintf(stdout,"%s\n",tmp);
  free(tmp);
}

Or this:
Code:

char *tmp;
int i=0;
while(i<=3000){
  if((tmp=(char*)malloc(sizeof(char)*strlen("TEST")))==NULL){
    perror("malloc");
    exit(1);
  }
  bzero(tmp,strlen(temp));
  strncpy(tmp,"TEST",strlen("TEST");
  fprintf(stdout,"%s\n",tmp);
}
free(tmp);


Where should I put the free?On the first one, after It runs a couple of time, it throws me an invalid free pointer error, and the other works fine, but shouldn't i use realloc instead of malloc for the second version???

Thanks a lot.

Zarnick


The first one but I don't see what you're trying to accomplish with the code you wouldn't need to continually malloc and free it to use it over and over.
Oh and casting malloc serves no purpose in C, in C type coercian from a void to any other type is done automatically and malloc returns a void pointer which can therefor be anything no need of a cast.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Tue Dec 20, 2005 4:57 pm    Post subject: Reply with quote

Interesting (didn't now about the cast), here's my real application:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

void usage(char *pname){
  fprintf(stdout,"Usage:%s <dir>\n",pname);
  exit(0);
}

int main(int argc, char *argv[]){
  DIR *dir=NULL;
  struct dirent *entry=NULL;
  struct stat info;
  char *tmpPath=NULL;
  int tmpSize=0;
  int fsize=0;
  int dsize=0;

  if(argc!=2){
    usage(argv[0]);
  }
  if((dir=opendir(argv[1]))==NULL){
    perror("opendir");
    exit(1);
  }
  while((entry=readdir(dir))!=NULL){
    fprintf(stdout,"[*]Name=%s\n",entry->d_name);
    tmpSize=strlen(argv[1])+strlen(entry->d_name)+1;
    if((tmpPath=(char*)malloc(sizeof(char)*tmpSize))==NULL){
      perror("malloc");
      exit(2);
    }
    bzero(tmpPath,tmpSize);
    snprintf(tmpPath,tmpSize,"%s%s",argv[1],entry->d_name);
    if(tmpPath[tmpSize]!='\0'){
      tmpPath[tmpSize]='\0';
    }
    lstat(tmpPath,&info);
    if(S_ISREG(info.st_mode)){
      fsize=info.st_size;
      dsize+=fsize;
      fprintf(stdout,"[*]File Size=%d\n",fsize);
    }
  }
  fprintf(stdout,"[*]Dir Size=%d\n",dsize);
  closedir(dir);
  free(tmpPath);
  return 0;
}

It's a simple program to read the contents of one (and only one) directory, if I put the free inside the while(on the end of it), here's the output when trying to read /usr/bin:
Quote:

.
.(strip)
.
[*]Name=gconfsharp-schemagen
[*]File Size=63
[*]Name=ginstall
[*]Name=Mail
[*]Name=boot-admin
[*]File Size=90236
*** glibc detected *** free(): invalid next size (fast): 0x0804a018 ***
Aborted

When instead I put the free after the while, it goes perfectly...

Any clues???

thanks a lot.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
hugo
Forum Fanatic
Forum Fanatic


Joined: 14 Jun 2003
Posts: 16777215
Location: Netherlands, Europe

Offline

PostPosted: Tue Dec 20, 2005 6:05 pm    Post subject: Reply with quote

Zarnick wrote:
Going allong with the free, wich one of these two codes are more acurate?

Depends on what you want to do. If it is required that the memory you want to use is 'fresh' everytime (because thats what you do in the loop), then the first code snippet would be better, because you actually free() the memory from inside the loop.

The second code snippet only frees the last assigned memory location assigned to tmp. In other words: you're leaking memory.

If the free( ) is outside the loop, the malloc( ) should be too, like so:
Code:

char *tmp = (char*)malloc(sizeof(char)*strlen("TEST"));
int i=0;
if(tmp==NULL){
    perror("malloc");
    exit(1);
}

while(i<=3000){
  bzero(tmp,strlen(temp));
  strncpy(tmp,"TEST",strlen("TEST");
  fprintf(stdout,"%s\n",tmp);
}
free(tmp);


Or, if the memory really needs to be allocated freshly for some reason, do this:
Code:

char *tmp;
int i=0;

while(i<=3000){
    if((tmp=(char*)malloc(sizeof(char)*strlen("TEST")))==NULL){
        perror("malloc");
        exit(1);
    }
    bzero(tmp,strlen(temp));
    strncpy(tmp,"TEST",strlen("TEST");
    fprintf(stdout,"%s\n",tmp);

    free(tmp);
}


Hope this helps.
Back to top
View user's profile Send private message
Sysop_fb
Just Arrived
Just Arrived


Joined: 27 Sep 2005
Posts: 0
Location: Iraq for the moment

Offline

PostPosted: Tue Dec 20, 2005 6:13 pm    Post subject: Reply with quote

Well the reason casting it is bad is because you're basically saying 'Hey compiler! I'm smarter then you so shuty!'
As an example casting malloc and not #includeing stdlib.h won't give an error but causes undefined behavior.

On your code either way works for me inside the while loop or not except for the blatent memory leak in one.
What O/S are you running?

Anyway basically what not free()ing and continually remallocing that memory is doing is just pointing that same pointer already pointing to allocated memory to new memory, which has the potential to cause memory leaks.
Since DMA isn't exactly my forte` I'll let someone else take it from here so I don't mislead you Razz

EDIT - See Hugo beat me I'm such a slow typer with out my 5th cup of coffee in the morning Razz
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Tue Dec 20, 2005 7:15 pm    Post subject: Reply with quote

Ok, so it did help, what I've meant with the example was that I was having a similar problem(as you can see on my program that reads a directory), after that I've tried to create the example in my pc and it worked fine, both versions(of course, the second one had a balantly memory leak), which makes me think that the error I'm getting may not be because of malloc or free, however if it isn't this, I really don't know what it is, one thing I've tried was to substitute tmpSize, to 1000(hard coded), and it worked fine, no free corruption...however this is just not elegant, and may cause to a lot of problems(for example, a complete directory with more then 1000 chars).

Any clue on what must be the problem???

As you can see I'm running Linux...(these behavior was seen on both Slackware and Gentoo, and even FreeBSD, wich makes me think that it IS a programer(that's me) error)...
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Sysop_fb
Just Arrived
Just Arrived


Joined: 27 Sep 2005
Posts: 0
Location: Iraq for the moment

Offline

PostPosted: Tue Dec 20, 2005 7:24 pm    Post subject: Reply with quote

Zarnick wrote:
Ok, so it did help, what I've meant with the example was that I was having a similar problem(as you can see on my program that reads a directory), after that I've tried to create the example in my pc and it worked fine, both versions(of course, the second one had a balantly memory leak), which makes me think that the error I'm getting may not be because of malloc or free, however if it isn't this, I really don't know what it is, one thing I've tried was to substitute tmpSize, to 1000(hard coded), and it worked fine, no free corruption...however this is just not elegant, and may cause to a lot of problems(for example, a complete directory with more then 1000 chars).

Any clue on what must be the problem???

As you can see I'm running Linux...(these behavior was seen on both Slackware and Gentoo, and even FreeBSD, wich makes me think that it IS a programer(that's me) error)...


Hmm with that free out of the while loop on some large directories doing malloc over and over could of allocated all of your system memory, especially if you have some processes running in the background Razz
Or corrupted a block of memory and malloc would occasionally hit it.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Tue Dec 20, 2005 7:33 pm    Post subject: Reply with quote

Yeap, however if I put it inside the while, I get an free corruption error. :O

It seems that fixing the size to 255 does work, and may be assumed as a workaroung, I can put the free inside the while and not leaking memory, however this is just nonsense, if I fix in 500 I can read only one item inside the directory Confused If this makes sense to any of you, please do enlight me....
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Sysop_fb
Just Arrived
Just Arrived


Joined: 27 Sep 2005
Posts: 0
Location: Iraq for the moment

Offline

PostPosted: Tue Dec 20, 2005 11:23 pm    Post subject: Reply with quote

Zarnick wrote:
Yeap, however if I put it inside the while, I get an free corruption error. :O

It seems that fixing the size to 255 does work, and may be assumed as a workaroung, I can put the free inside the while and not leaking memory, however this is just nonsense, if I fix in 500 I can read only one item inside the directory Confused If this makes sense to any of you, please do enlight me....


This is working for me, disregard the #include <unix.h> since you're probably using glibc :O
Program also compiled on windows XP in bloodshed Dev-C and ran fine.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unix.h>

void usage(char *pname){
  fprintf(stdout,"Usage:%s <dir>\n",pname);
  exit(0);
}

int main(int argc, char** argv){
  DIR *dir=NULL;
  struct dirent *entry=NULL;
  struct stat info;
  char *tmpPath=NULL;
  char *tmp=NULL;
  int tmpSize=0;
  int fsize=0;
  int dsize=0;

  if(argc!=2){
    usage(argv[0]);
  }
  if((dir=opendir(argv[1]))==NULL){
    perror("opendir");
    exit(1);
  }
  while((entry=readdir(dir))!=NULL){
    fprintf(stdout,"[*]Name=%s\n",entry->d_name);
    tmpSize=strlen(argv[1])+strlen(entry->d_name)+1;
    if(tmpPath == NULL)
    {
          if((tmpPath=malloc(sizeof(char) * tmpSize))==NULL)
          {
               perror("malloc");
               exit(2);
           }
    } else {
           if((tmp=realloc(tmpPath,sizeof(char) * tmpSize))==NULL)
           {
                 printf("Memory Allocation Failed\n");
                 free(tmpPath);
                 exit(2);
            }
            tmpPath=tmp;
    }

    bzero(tmpPath,tmpSize);
    snprintf(tmpPath,tmpSize,"%s%s",argv[1],entry->d_name);
    if(tmpPath[tmpSize]!='\0'){
      tmpPath[tmpSize]='\0';
    }
    lstat(tmpPath,&info);
    if(S_ISREG(info.st_mode)){
      fsize=info.st_size;
      dsize+=fsize;
      fprintf(stdout,"[*]File Size=%d\n",fsize);
    }
  }
  fprintf(stdout,"[*]Dir Size=%d\n",dsize);
  free(tmpPath);
  closedir(dir);
  return 0;
}


Last edited by Sysop_fb on Wed Dec 21, 2005 12:24 am; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Tue Dec 20, 2005 11:49 pm    Post subject: Reply with quote

Yes, this will work, but have you seen the code?There's a huge memory leak, if I put the free(tmpPath) after the while, here is the buggy code, in theory it should work, but the free amuses himself byt throwing an error:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

void usage(char *pname){
  fprintf(stdout,"Usage:%s <dir>\n",pname);
  exit(0);
}

int main(int argc, char *argv[]){
  DIR *dir=NULL;
  struct dirent *entry=NULL;
  struct stat info;
  char *tmpPath=NULL;
  int tmpSize=0;
  int fsize=0;
  int dsize=0;
  if(argc!=2){
    usage(argv[0]);
  }
  if((dir=opendir(argv[1]))==NULL){
    perror("opendir");
    exit(1);
  }
  while((entry=readdir(dir))!=NULL){
    sleep(0.5);
    fprintf(stdout,"[*]Name=%s\n",entry->d_name);
    tmpSize=strlen(argv[1])+strlen(entry->d_name);
    if((tmpPath=(char*)malloc(sizeof(char)*tmpSize))==NULL){
      perror("malloc");
      exit(2);
    }
    bzero(tmpPath,tmpSize);
    strncpy(tmpPath,argv[1],strlen(argv[1]));
    strncat(tmpPath,entry->d_name,strlen(entry->d_name));

    if(tmpPath[tmpSize]!='\0'){
      tmpPath[tmpSize]='\0';
    }
    lstat(tmpPath,&info);
    if(S_ISREG(info.st_mode)){
      fsize=info.st_size;
      dsize+=fsize;
    }
    bzero(tmpPath,strlen(tmpPath));
    free(tmpPath);
  }
  fprintf(stdout,"[*]Dir Size=%d\n",dsize);
  closedir(dir);
  //free(tmpPath);
  return 0;
}


And this is the error:
Quote:

*** glibc detected *** free(): invalid next size (fast): 0x0804b028 ***


However, if I hardcode tmpSize to 255 it works withouth a glintch Confused !!!!

See what I mean?
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Sysop_fb
Just Arrived
Just Arrived


Joined: 27 Sep 2005
Posts: 0
Location: Iraq for the moment

Offline

PostPosted: Wed Dec 21, 2005 12:11 am    Post subject: Reply with quote

My code didn't have a memory leak(as far as I know) because it only mallocd tmpPath that one time because of the if statement
if(tmpPath == NULL)

After that I used a temporary pointer for realloc then set tmpPath to that new realloced memory.

Like I said though I'm not the greatest person with Dynamic Memory Allocation... just starting to get somewhat of a grasp on it after playing around with stuff Razz
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Zarnick
Just Arrived
Just Arrived


Joined: 27 Mar 2003
Posts: 1
Location: Brazil

Offline

PostPosted: Wed Dec 21, 2005 12:43 am    Post subject: Reply with quote

Can you show me your code?I did that and it worked only partially, if I get my home dir(53 file) works ok, but for the /usr/bin(1824 files) it launches me an realloc error:
Quote:

*** glibc detected *** realloc(): invalid next size: 0x0804a008 ***


Thanks.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   

Post new topic   Reply to topic   Printer-friendly version    Networking/Security Forums Index -> Programming and More All times are GMT + 2 Hours
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

Community Area

Log in | Register