Using Malloc in C

Networking/Security Forums -> Programming and More

Author: MattALocation: Eastbourne + London PostPosted: Mon Dec 19, 2005 3:44 pm    Post subject: Using Malloc in C
    ----
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;
}

Author: hugoLocation: Netherlands, Europe PostPosted: Mon Dec 19, 2005 4:34 pm    Post subject: Re: Using Malloc in C
    ----
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

Author: MattALocation: Eastbourne + London PostPosted: Mon Dec 19, 2005 10:04 pm    Post subject:
    ----
Cheers Hugo. Even threw in the free command to free up the memory too Wink

Author: capiLocation: Portugal PostPosted: Tue Dec 20, 2005 12:18 am    Post subject: Re: Using Malloc in C
    ----
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).

Author: ZarnickLocation: Brazil PostPosted: Tue Dec 20, 2005 3:43 pm    Post subject:
    ----
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

Author: Sysop_fbLocation: Iraq for the moment PostPosted: Tue Dec 20, 2005 4:44 pm    Post subject:
    ----
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.

Author: ZarnickLocation: Brazil PostPosted: Tue Dec 20, 2005 4:57 pm    Post subject:
    ----
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.

Author: hugoLocation: Netherlands, Europe PostPosted: Tue Dec 20, 2005 6:05 pm    Post subject:
    ----
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.

Author: Sysop_fbLocation: Iraq for the moment PostPosted: Tue Dec 20, 2005 6:13 pm    Post subject:
    ----
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

Author: ZarnickLocation: Brazil PostPosted: Tue Dec 20, 2005 7:15 pm    Post subject:
    ----
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)...

Author: Sysop_fbLocation: Iraq for the moment PostPosted: Tue Dec 20, 2005 7:24 pm    Post subject:
    ----
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.

Author: ZarnickLocation: Brazil PostPosted: Tue Dec 20, 2005 7:33 pm    Post subject:
    ----
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....

Author: Sysop_fbLocation: Iraq for the moment PostPosted: Tue Dec 20, 2005 11:23 pm    Post subject:
    ----
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

Author: ZarnickLocation: Brazil PostPosted: Tue Dec 20, 2005 11:49 pm    Post subject:
    ----
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?

Author: Sysop_fbLocation: Iraq for the moment PostPosted: Wed Dec 21, 2005 12:11 am    Post subject:
    ----
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

Author: ZarnickLocation: Brazil PostPosted: Wed Dec 21, 2005 12:43 am    Post subject:
    ----
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.



Networking/Security Forums -> Programming and More


output generated using printer-friendly topic mod, All times are GMT + 2 Hours

Page 1 of 1

Powered by phpBB 2.0.x © 2001 phpBB Group