Splint: строки значений [], используемые перед определением с динамическим массивом

Я использую динамический массив строк в C:

char** strings;

Я инициализирую его:

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

И скопируйте пару фиктивных строк:

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

Тем не менее, когда я пытаюсь напечатать это:

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

Я получаю эту ошибку от 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)

Такая проверка на NULL не поможет:

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

поскольку strings[i] все еще используется «до определения».

Любые идеи о том, как решить эту проблему?

Изменить: я думаю, что вместо этого я попробую это со связанным списком.

Кроме того, полный листинг кода:

#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;
}

person Olle Härstedt    schedule 15.08.2014    source источник
comment
Я запускаю ваш код на моем Linux FC14, и успешно, вывод: строка [0] = строка приветствия [1] = строка приветствия [2] = строка приветствия [3] = строка приветствия [4] = строка приветствия [5] = привет строка[6] = привет строка[7] = привет строка[8] = привет строка[9] = привет   -  person dbndhjefj    schedule 15.08.2014
comment
@szpal Splint жалуется, хотя ... в вопросе. Почему речь идет о значениях r? :-с   -  person doctorlove    schedule 15.08.2014
comment
Не имеет отношения, но strncpy(strings[i], str, strlen(str) + 1); лучше писать как strcpy(strings[i], str);   -  person M.M    schedule 15.08.2014
comment
Я не вижу никаких ошибок в этом коде... возможно, это ошибка в шине. Возможно, попробуйте установить все 10 указателей в strings[] на NULL после вашего malloc - возможно, шина не понимает в цикле Print Strings, что невозможно добраться до нее без фактического назначения строки   -  person M.M    schedule 15.08.2014


Ответы (2)


У меня нет Splint на моей машине, поэтому я не могу протестировать его, просто другой способ выполнить вашу задачу:

#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;
}
person dbndhjefj    schedule 15.08.2014
comment
Это хорошее предложение, но, увы, недостаточно для моих нужд. У меня есть эта логика внутри функции, и я хочу вернуть массив строк. Если я статически выделю strings[max][len], память будет освобождена при выходе из функции. Возможно, мне нужно было бы вместо этого использовать связанный список. - person Olle Härstedt; 15.08.2014
comment
Я думаю, если вы хотите использовать этот код в функции, вам нужно передать адрес «строки» в качестве аргумента или определить «строки» как глобальную переменную. Удачи! - person dbndhjefj; 15.08.2014

Избегайте создания прерывистой памяти, было бы лучше, если бы вы выделяли память в одном вызове malloc.

  • Память может быть освобождена одним бесплатным вызовом вместо нескольких бесплатных вызовов.
  • max_rows * sizeof(char) выделит 2 * 1
  • ((strlen(str) * N) + 1) будет выделять память для каждого элемента N.

Вот мой подход

#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;
}
person Shushant    schedule 15.08.2014