динамический массив в C ++ - условный переход или перемещение зависит от неинициализированных значений - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть этот код:

#include <iostream>

using namespace std;

int main()
{
    int tmp = 5;
    int * arr = new int[tmp];
    for(int i = 0; i < 7; i++)
    {
        if (i == tmp) //if count of values is equal to max size of arr then create new arr with more space
        {
            int * s = new int[tmp]; // reserve memory
            for(int i = 0; i < (tmp); i++)
            {
                s[i] = arr[i]; //fill reserve memory with values from array arr
            }
            delete [] arr; // delete arr array
            tmp *= 2; //twice more space for array
            arr = new int[tmp]; //create new arr with twice more space
            for (int i = 0; i < (tmp / 2); i++)
            {
                arr[i] = s[i]; // add values from old short arr to new arr with more space
            }
            delete [] s; // delete reserve memory
        }
        arr[i] = 1; //add 1 to position i in array
    }
    //show array
    for (int j = 0; j < tmp; j++)
        cout << arr[j] << " ";
    cout << endl;
    delete [] arr; //delete arr
    return 0;
}

И я не понимаю эту ошибку от valgrind:

==2664== 
==2664== Conditional jump or move depends on uninitialised value(s)
==2664==    at 0x4EBFCDE: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EC02BC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4ECC06D: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x400AE1: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664==  Uninitialised value was created by a heap allocation
==2664==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2664==    by 0x400A2D: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664== 
==2664== Use of uninitialised value of size 8
==2664==    at 0x4EBFBC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EBFD05: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EC02BC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4ECC06D: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x400AE1: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664==  Uninitialised value was created by a heap allocation
==2664==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2664==    by 0x400A2D: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664== 
==2664== Conditional jump or move depends on uninitialised value(s)
==2664==    at 0x4EBFBCF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EBFD05: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EC02BC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4ECC06D: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x400AE1: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664==  Uninitialised value was created by a heap allocation
==2664==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2664==    by 0x400A2D: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664== 
==2664== Conditional jump or move depends on uninitialised value(s)
==2664==    at 0x4EBFD33: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4EC02BC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x4ECC06D: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==2664==    by 0x400AE1: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664==  Uninitialised value was created by a heap allocation
==2664==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2664==    by 0x400A2D: main (in /home/vojta/Dokumenty/C++/vstup do pole/a.out)
==2664== 
1 1 1 1 1 1 1 0 0 0 
==2664== 
==2664== HEAP SUMMARY:
==2664==     in use at exit: 0 bytes in 0 blocks
==2664==   total heap usage: 3 allocs, 3 frees, 80 bytes allocated
==2664== 
==2664== All heap blocks were freed -- no leaks are possible
==2664== 
==2664== For counts of detected and suppressed errors, rerun with: -v
==2664== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 0 from 0)

Я обнаруживаю, что если я выполню этот цикл

for(int i = 0; i < 7; i++)
{

до 10 не только до 7, valgrind не показывает никаких ошибок.Я хочу спросить вас, если моя идея о том, чтобы некоторые позиции в массиве были пустыми, неверна?Я не знаю, правильный ли мой код для создания массива в зависимости от того, сколько значений вы хотите добавить.Существуют ли другие способы, как создать массив большего размера, если он вам нужен?

Я пытался запустить valgrind с --track-originins = да, но не смог найти в нем ответа.

Я новичок в C ++, поэтому я рад за все новые идеиили намеки.Спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

На ваш вопрос уже дан ответ, но в следующий раз, знайте, что если вы скомпилируете свой код с флагом -g3 в g++, valgrind также покажет вам номера строк, в которых возникли проблемы.Например, компиляция с g++ teste.cpp -g3 и valgrind --track-origins=yes ./a.out даст вам:

==20609== Memcheck, a memory error detector
==20609== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==20609== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==20609== Command: ./a.out
==20609== 
==20609== Conditional jump or move depends on uninitialised value(s)
==20609==    at 0x4F3CCAE: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CEDC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F493F9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x400AE0: main (teste.cpp:31)
==20609==  Uninitialised value was created by a heap allocation
==20609==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20609==    by 0x400A2B: main (teste.cpp:20)
==20609== 
==20609== Use of uninitialised value of size 8
==20609==    at 0x4F3BB13: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CCD9: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CEDC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F493F9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x400AE0: main (teste.cpp:31)
==20609==  Uninitialised value was created by a heap allocation
==20609==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20609==    by 0x400A2B: main (teste.cpp:20)
==20609== 
==20609== Conditional jump or move depends on uninitialised value(s)
==20609==    at 0x4F3BB1F: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CCD9: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CEDC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F493F9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x400AE0: main (teste.cpp:31)
==20609==  Uninitialised value was created by a heap allocation
==20609==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20609==    by 0x400A2B: main (teste.cpp:20)
==20609== 
==20609== Conditional jump or move depends on uninitialised value(s)
==20609==    at 0x4F3CD0C: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F3CEDC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x4F493F9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==20609==    by 0x400AE0: main (teste.cpp:31)
==20609==  Uninitialised value was created by a heap allocation
==20609==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20609==    by 0x400A2B: main (teste.cpp:20)
==20609== 
1 1 1 1 1 1 1 0 0 0 
==20609== 
==20609== HEAP SUMMARY:
==20609==     in use at exit: 72,704 bytes in 1 blocks
==20609==   total heap usage: 5 allocs, 4 frees, 73,808 bytes allocated
==20609== 
==20609== LEAK SUMMARY:
==20609==    definitely lost: 0 bytes in 0 blocks
==20609==    indirectly lost: 0 bytes in 0 blocks
==20609==      possibly lost: 0 bytes in 0 blocks
==20609==    still reachable: 72,704 bytes in 1 blocks
==20609==         suppressed: 0 bytes in 0 blocks
==20609== Rerun with --leak-check=full to see details of leaked memory
==20609== 
==20609== For counts of detected and suppressed errors, rerun with: -v
==20609== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 0 from 0)

Это говорит о том, что неинициализированные значения использовались в строке 31, и они были созданы новыми в строке 20.

Это может быть очень полезно.

0 голосов
/ 21 декабря 2018

Как только этот массив увеличится до пяти int, показанный код увеличит его до десяти элементов и приступит к добавлению двух дополнительных int s, # 5 и # 6, к массиву (я использую индексы на основе 0для ссылки на отдельные int s в массиве).

Цикл for в конце попытается вывести все 10 значений массива.Включая неинициализированные значения, с № 7 по № 9.Это то, что говорит вам valgrind.

Диагностика valgrind практически не поддается расшифровке, потому что неинициализированное использование памяти фактически не происходит, пока вы не углубитесь в недра библиотеки ввода / вывода.Ошибка заключается в функции main(), но все, что она делает, - передает ссылку на неинициализированное значение в библиотеку ввода / вывода.Это не вызывает неопределенного поведения до тех пор, пока неинициализированное значение фактически не будет захвачено внутри библиотеки ввода-вывода для форматирования.

PS: массив сначала растут путем копирования содержимого массива в новый sмассив.Исходный arr удаляется и заменяется новым 10 элементом arr, затем пять значений копируются обратно из s и s удаляется.

Это много ненужного копирования.Достаточно выделить новый массив из 10 элементов, скопировать в него существующее содержимое, затем удалить оригинал и заменить его новым массивом.

...