View Single Post
Old 24th November 2011
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by Daffy View Post
When I enter a name (for example in 'artist') and it has 40 characters, taglist.artist stores it properly (with malloc() ).
Not from the code posted. From above:
Code:
    printf("Enter artist name:\n");/* ask for input, read to array, remove enter */
    char *artist = (char*) malloc(50 *sizeof(char));
    fgets(taglist.artist, LEN, stdin);
    remove_enter(taglist.artist);
Here, artist gets 50 bytes of heapspace (assuming a character is represented in one byte...) through malloc(), & then nothing is done with the heapspace until it is freed at the end of main(). Any keyboard entry is read directly into the global structure instance which was fully defined at compile-time.

Recognize that the name "artist" is being used in two completely different contexts. One, naming a field within a global structure. The other, a variable defined within main(). To illustrate, study the following example:
Code:
$ cat addresses.c
#include <stdio.h>

struct struct_name {
    int foo;
} global_sn_instance;

int main()
{
    struct struct_name sn_instance; 
    int foo;

    printf("global struct:\t%u\n", (void*) &global_sn_instance.foo);
    printf("local struct:\t%u\n", (void*) &sn_instance.foo);
    printf("local variable:\t%u\n", (void*) &foo);

    return 0;
}
$ gcc addresses.c
$ a.out
global struct:  1006645888
local struct:   3485315520
local variable: 3485315516
$
The addresses of each "foo" is different.
Quote:
The problem is when I pass the value in char *command[LEN], it stores only the 30 first characters.
I suspect you are using code which has not been posted as the last example above, only the artist & track name are being initialized from keyboard input. My recommendation would be add printf() statements after each keyboard entry such that you can verify how input is getting copied about. I would also suggest dumping all elements in your constructed command variable before spawning the child process. These are debugging aides which can be taken out later if desired.
Quote:
Do I need to use malloc() on every array object?
There are two ends to this continuum. Either the entire structure could be allocated from heapspace (memory grabbed at runtime...), or individual fields. Consider the following example:
Code:
$ cat memory.c
#include <stdio.h>
#include <stdlib.h>

struct a {
    char *s;
};

struct b {
    char s[8];
};

int main()
{
    struct a a;
    struct b *p;

    a.s = (char*) malloc(8 * sizeof(char));
    scanf("%s", a.s);

    p = (struct b*) malloc(sizeof(struct b));
    scanf("%s", p->s);
    
    printf("a:\t%s\n", a.s);
    printf("b:\t%s\n", p->s);

    free(a.s);
    free(p);

    return 0;
}
$ gcc memory.c
$ a.out 
abc
xyz
a:      abc
b:      xyz
$
Note that I used the word "continuum". Stranger scenarios can exist, but the code gets further twisted. At this point, you should be making sure you understand the basics before getting too exotic.
Quote:
And a last question for free(). When I use it on a char object inside a structure, I target it by name (for this example free(artist)) or by first referring to the structure name (free(taglist.artist))? Is it a good solution to free after use the entire structure by free(taglist)?
free() should only be called on addresses which have been allocated through malloc() or any of its relatives. Calling free() on anything which has not been allocated through malloc() (or its relatives...) could very well send execution into the weeds. It all depends upon how heapspace management is written for the specific processor. On some platforms, it may work for any pointer. Others, it won't. The processor agnostic answer is to only call free() on objects previously allocated on the heap.

Last edited by ocicat; 24th November 2011 at 04:21 PM.
Reply With Quote