Home > OS >  array of pointers with malloc and strcpy code. Is there anything wrong with this code if valgrid -s
array of pointers with malloc and strcpy code. Is there anything wrong with this code if valgrid -s

Time:10-27

I have this simple code for array of pointers with malloc and strcpy.

First I declared and defined array of pointers with char *tokens[3]; tokens[0]=malloc(strlen("<html>") 1); then printf and free is this code safe from leaks for memoryc

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

char *tokens[3];

int main()
{
    tokens[0]=malloc(strlen("<html>") 1);
    strcpy(tokens[0],"<html>");
    
    printf("%s\n",tokens[0]);
    free(tokens[0]);

}

Also please do let me know how to allocate in one line three pointers in the array tokens I tried like this but this does not work

  tokens[0]=malloc((strlen("<html>") 1) (strlen("<title>") 1));

CodePudding user response:

malloc.h is non-standard and deprecated, use stdlib.h instead. Apart from that, the code looks correct for allocating room for the first string out of 3. (As someone said in comments, you should add error handling though.)

Also please do let me know how to allocate in one line three pointers in the array tokens I tried like this but this does not work

The whole point of having an array of pointers instead of a 2D array of characters is that you can set individual string lengths for each pointed-at string. So it doesn't make much sense to allocate room in a single line unless you have very specialized requirements. So the question here is rather why you want heap allocation in the first place.

Assuming you wish to replace the strings at a later point and realloc memory, then you could simply initialize them with some default values like this:

const char* def[STR_N] =
{
  "<html>",
  "<foo>",
  "<bar>",
};
char *tokens[STR_N];

for(size_t i=0; i<STR_N; i  )
{
  tokens[i] = malloc(strlen(def[i]) 1);
  strcpy(tokens[i],def[i]);
  printf("%s\n",tokens[i]);
}

Also strdup is currently considered somewhat bad practice since it's non-standard, but it looks like it will get added to the standard in the upcoming C2x, so it's another option, rather than doing allocation copy in 2 steps.

CodePudding user response:

is this code safe from leaks for memoryc

Almost. malloc() may return NULL. Best to test for that and make sure later code does not use free'd memory.

tokens[0]=malloc(strlen("<html>") 1);
if (tokens[0]) {
  strcpy(tokens[0],"<html>");
  printf("%s\n",tokens[0]);
  free(tokens[0]);
  tokens[0] = NULL; // Help make sure following code does not use stale pointer
}

how to allocate in one line three pointers in the array tokens

For a learner, I reccomend instead 3 malloc() calls.

But to use one call, if code knew the 3 sizes needed:

size_t sz[3];
sz[0] = strlen("<html>")   1;
sz[1] = ...; // TBD
sz[2] = ...; // TBD

// Allocate the sum
tokens[0] = malloc(sz[0]   sz[1]   sz[2]);
if (tokens[0]) {
  tokens[1] = tokens[0]   sz[0];
  tokens[2] = tokens[1]   sz[1];
  
  // use token[]

  free(tokens[0]); // Only 1 free
  tokens[0] = tokens[1] = tokens[2] = NULL;
}

Note: Non-looped code here for clarity. Better to use loops than repeat code.

CodePudding user response:

Beware, initialization and assignment are different animals. You can initialize an array as a whole but only at its definition. Once this is done, you can only assign to its individual elements.

And as you want to compute the size of the elements of the array, it cannot have static duration (cannot be declared as a global array) but must be automatic (declared inside a function):

...
int main() {
    char* tokens[] = { malloc(strlen("<html>") 1), malloc(strlen("<title>") 1),
        malloc(strlen("foo")   1) };
    strcpy(tokens[0], "<html>");
    strcpy(tokens[1], "<title>");
    strcpy(tokens[2], "foo");
    ...
    for (int i = 0; i < 3; i  ) {
        free(tokens[i]);
    }
    ...
}

BTW, above code is only for demonstation purpose, I cannot imagine a real world usage for allocating dynamic strings to later feed them from litteral strings...

Normal code would be:

const char *tokens = { "<html>", "<title>", "foo"};

with no malloc or free call...

CodePudding user response:

To answer the second part of your question first, to define and provide memory for an array in one line, you need to do the following:

char *tokens;
tokens = malloc(sizeof(char) * (strlen("<html>") 1) * 3);

Note that the array's size is not specified initially, but only in the malloc call. You can free the memory you requested by running:

free(tokens);

To follow up on Quimby's comment, this malloc call creates a single, contiguous block of memory, with length 1 * (6 1) * 3, or 21 bytes. To index into the elements, you'd need either:

&tokens[0]; //beginning of first string
$tokens[7]; //beginning of second string
//or
tokens   0; //beginning of first string
tokens   7; //beginning of second string
  •  Tags:  
  • c
  • Related