2

I'm using a dynamic array of strings in C:

char** strings;

I initialize it:

int max = 10;
strings = malloc(sizeof(char*) * max);

And copy a couple of dummy strings:

char* str = "dummy";
for (int i = 0; i < max; i++) {
  strings[i] = malloc(strlen(str) + 1);
  strncpy(strings[i], str, strlen(str) + 1);
}

Yet when I try to print this:

for (int i = 0; i < max; i++)
  printf("array = %s", strings[i])

I get this error from Splint:

Value strings[] used before definition
  An rvalue is used that may not be initialized to a value on some execution
  path. (Use -usedef to inhibit warning)

Checking for NULL like this will not help:

for (int i = 0; i < max; i++)
  if (strings[i] != NULL)
    printf("array = %s", strings[i])

since strings[i] is still used "before definition".

Any ideas on how to solve this?

Edit: Will try this with a linked list instead, I think.

Also, complete code listing:

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

int main()
{
    char** strings;
    int i;
    int max = 10;
    char* str = "hello";

    // Dynamic array with size max
    strings = malloc(sizeof(char*) * max);

    // Abort if NULL
    if (strings == NULL)
        return (-1);

    // Define strings
    for (i = 0; i < max; i++)
    {
        strings[i] = malloc(strlen(str) + 1);

        // Abort if NULL
        if (strings[i] == NULL)
        {
            // Undetected memory leak here!
            free(strings);
            return (-1);
        }

        strncpy(strings[i], str, strlen(str) + 1);
    }

    // Print strings
    for (i = 0; i < max; i++)
    {
        if (strings[i] != NULL)
            printf("string[%d] = %s\n", i, strings[i]);
    }

    // Free strings
    for (i = 0; i < max; i++)
    {
        if (strings[i] != NULL)
            free(strings[i]);
    }
    free(strings);

    return 0;
}
Olle Härstedt
  • 3,799
  • 1
  • 24
  • 57
  • I run your code on my FC14 linux, and success, the output is: string[0] = hello string[1] = hello string[2] = hello string[3] = hello string[4] = hello string[5] = hello string[6] = hello string[7] = hello string[8] = hello string[9] = hello – szpal Aug 15 '14 at 11:32
  • @szpal Splint is complaining though... in the question. Why is it on about r values? :-s – doctorlove Aug 15 '14 at 11:34
  • 2
    Unrelated, but `strncpy(strings[i], str, strlen(str) + 1);` is better written as `strcpy(strings[i], str);` – M.M Aug 15 '14 at 11:40
  • 1
    I don't see any bugs in this code... perhaps it is a bug in splint. Maybe try setting all 10 pointers in `strings[]` to `NULL` after your `malloc` - perhaps splint doesn't realize in the `Print Strings` loop that it is not possible to reach it without the string actually having being assigned – M.M Aug 15 '14 at 11:41

2 Answers2

0

I do not have Splint on my machine, so i cannot test with it, just an another way to your task:

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

int main()
{
  int i, len, max;
  char* str = "hello";

  len = strlen(str) + 1;
  max = 10;

  char strings[max][len];

  for (i = 0; i < max; i++) {
    strcpy(strings[i], str);
  }

  for (i = 0; i < max; i++) {
    printf("string[%d] = %s\n", i, strings[i]);
  }

  return 0;
}
szpal
  • 647
  • 9
  • 27
  • That's a good suggestions, but alas not sufficient for my need. I have this logic within a function and want to return an array of strings. If I statically allocate `strings[max][len]`, the memory will be freed when exiting the function. Maybe I would need to use a linked list instead. – Olle Härstedt Aug 15 '14 at 12:43
  • I think if you want use this code in a function, then you need pass the address of 'strings' as an argument, or define 'strings' as a global variable. Good luck! – szpal Aug 15 '14 at 13:29
0

Avoid creating non-continuous memory it would be better approach if you allocate memory in single malloc call.

  • Memory can be freed in single free call instead of multiple free call
  • max_rows * sizeof(char) will allocate 2 * 1
  • ((strlen(str) * N) + 1) will allocate memory for every N element.

Here is my approch

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

int main(){

    size_t max_rows = 2;

    char* str = "dummpy";
    char* vec_s = (char *) malloc( max_rows * sizeof(char) * ((strlen(str) * max_rows) + 1));

    for (int i = 0; i < max_rows; i++){
        strcpy((vec_s + i), str);
        printf("vec_s[%d]=%s\n", i, (vec_s + i));
    }
    free(vec_s);
    return 0;
}
Olle Härstedt
  • 3,799
  • 1
  • 24
  • 57
Shushant
  • 1,625
  • 1
  • 13
  • 23