почему мои переменные не инициализированы?

Я сократил свой код до самого простого, чтобы изолировать свою проблему, я понял, в чем была моя проблема, но не могу ее решить. На самом деле, я даже не знаю, есть ли проблема.

У меня есть функция, предназначенная для инициализации неинициализированных переменных и повторной инициализации уже инициализированных переменных. Моя проблема в том, что переменные, которые я объявляю, кажутся инициализированными.

Вот что осталось от кода:

/**
  * This software defines the type TabDyn and gives the tools to manipulate it
  * 
  * TabDyn is conceptually an array of integers. The first element is the size while the others are the members of the array.
  *
  * Here are the function provided to manipulate TabDyn :
  *     td_clear(TabDyn* td) : Create the TabDyn object if non existant and initialize it to an empty one. If it exists, it empties it.
  *
  */

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

// TabDyn[0] := size
// tabDyn[i] := i^th element of the array, first index being 1 (i>1)
typedef int* TabDyn;

/**
  * param - TabDyn* td_ptr : address of a declared int
  * void : initialize {td_ptr} to an empty array (size=0, no member)
  */
void td_clear(TabDyn* td_ptr)
{
    //this is the size of each member of TabDyn and thus the size of an empty TabDyn
    size_t TabDynByteCount = sizeof(int); 

    //We must free initialized TabDyn variables
    if(td_ptr && *td_ptr) 
    {
        printf("INITIALIZED!\n"); //#TOREMOVE#
        free(*td_ptr);  
    }

    //Create TabDyn object of size = 0 and give it to param
    *td_ptr = calloc(1, TabDynByteCount);
}

/**
  * Contains various test of the TabDyn function to ensure a correct behaviour by testing it at runtime with Valgrind
  */
int main()
{
    //* TEST decl-init-free #VALID:v0.04#
    printf("\n--- TEST OF td_clear BATCH 1 ---\n");
    printf("Declaring TabDyn variable\n");
    TabDyn tabTestAllocate;
    printf("Initialising TabDyn variable\n");
    td_clear(&tabTestAllocate);
    printf("Freeing now useless variables\n");
    free(tabTestAllocate);
    //*/
    //* TEST decl-init-init-free
    printf("\n--- TEST OF td_clear BATCH 2 ---\n");
    printf("Declaring TabDyn variable\n");
    TabDyn tabTestAllocate2;
    printf("Initialising TabDyn variable\n");
    td_clear(&tabTestAllocate2);
    printf("Re-initialising TabDyn variable\n");
    td_clear(&tabTestAllocate2); // It is not a duplicate
    printf("Freeing now useless variables\n");
    free(tabTestAllocate2);
    //*/
}

И вот что говорит об этом Вальгринд:

--- TEST OF td_clear BATCH 1 ---
Declaring TabDyn variable
Initialising TabDyn variable
==10875== Conditional jump or move depends on uninitialised value(s)
==10875==    at 0x400654: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x4006CD: main (in /home/adrien/Documents/c/examen)
==10875== 
INITIALIZED!
==10875== Conditional jump or move depends on uninitialised value(s)
==10875==    at 0x4C2CDE1: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10875==    by 0x40066E: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x4006CD: main (in /home/adrien/Documents/c/examen)
==10875== 
==10875== Invalid free() / delete / delete[] / realloc()
==10875==    at 0x4C2CE2B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10875==    by 0x40066E: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x4006CD: main (in /home/adrien/Documents/c/examen)
==10875==  Address 0x400540 is in the Text segment of /home/adrien/Documents/c/examen
==10875==    at 0x400540: _start (in /home/adrien/Documents/c/examen)
==10875== 
Freeing now useless variables

--- TEST OF td_clear BATCH 2 ---
Declaring TabDyn variable
Initialising TabDyn variable
==10875== Conditional jump or move depends on uninitialised value(s)
==10875==    at 0x400654: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x40070D: main (in /home/adrien/Documents/c/examen)
==10875== 
INITIALIZED!
==10875== Conditional jump or move depends on uninitialised value(s)
==10875==    at 0x4C2CDE1: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10875==    by 0x40066E: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x40070D: main (in /home/adrien/Documents/c/examen)
==10875== 
==10875== Invalid free() / delete / delete[] / realloc()
==10875==    at 0x4C2CE2B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10875==    by 0x40066E: td_clear (in /home/adrien/Documents/c/examen)
==10875==    by 0x40070D: main (in /home/adrien/Documents/c/examen)
==10875==  Address 0xffefffe70 is on thread 1's stack
==10875== 
Re-initialising TabDyn variable
INITIALIZED!
Freeing now useless variables
==10875== 
==10875== HEAP SUMMARY:
==10875==     in use at exit: 0 bytes in 0 blocks
==10875==   total heap usage: 3 allocs, 5 frees, 12 bytes allocated
==10875== 
==10875== All heap blocks were freed -- no leaks are possible
==10875== 
==10875== For counts of detected and suppressed errors, rerun with: -v
==10875== Use --track-origins=yes to see where uninitialised values come from
==10875== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

но если я явно инициализирую свои переменные значением NULL, проблем больше не будет:

 TabDyn tabTestAllocate = NULL;
 TabDyn tabTestAllocate2 = NULL;

Разве мои переменные не должны инициализироваться значением NULL? Или мой оператор if не проверяет то, что я думаю, он проверяет?


person Adrien Horgnies    schedule 19.02.2016    source источник
comment
Не typedef указатели! Это запутывает ваш код, скрывая семантику, и подвержено ошибкам.   -  person too honest for this site    schedule 19.02.2016


Ответы (3)


Нет, их нельзя инициализировать до NULL, и они будут иметь неопределенные значения, поскольку они имеют автоматическую продолжительность хранения и не инициализируются явно.

N1256 6.7.8 Инициализация

10 Если объект с автоматическим сроком хранения не инициализирован явно, его значение неопределенно.

person MikeCAT    schedule 19.02.2016

Насколько я знаю, только статические переменные будут установлены в NULL при инициализации. Другие переменные будут указывать на случайные ячейки памяти со значением, хранящимся в этой ячейке памяти. Как программист, использующий C/C++, вы несете ответственность за использование памяти и за то, что хранится в этих местах (обычно используется термин «управление памятью»). Он не делает ничего из этой работы за вас.

person Careful Now    schedule 19.02.2016

Ваша переменная (tabTestAllocate) НЕ инициализирована (см.: Почему не указатели инициализирован с NULL по умолчанию? ). Это означает, что его значение не определено. Указатель на него (&tabTestAllocate) ясно определяется. Таким образом, в вашем операторе if td_ptr имеет определенное (не NULL) значение, а * td_ptr не определено. Но это не означает, что *td_ptr должен быть NULL, просто вы не знаете, что это такое, поэтому вы не можете заранее знать, будет ли условие истинным или нет.

person Bruno Golosio    schedule 19.02.2016