首页 > 解决方案 > C++ 中的动态数组 - 条件跳转或移动取决于未初始化的值

问题描述

我有这个代码:

#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 不显示任何错误。我想问你,如果我在数组中有一些位置为空的想法是错误的吗?我不知道我的代码对于创建数组是否正确,具体取决于您要添加多少值。它是否存在其他方式,如果需要,如何创建更大的数组?

我尝试使用 --track-origins=yes 运行 valgrind,但在其中找不到答案。

我是 C++ 新手,所以我对每一个新想法或提示都很满意。感谢您的时间。

标签: c++valgrind

解决方案


一旦这个数组增长到 5 int,显示的代码将它增长到 10 个元素,然后继续向int数组中添加两个额外的 s,#5 和 #6(我使用基于 0 的索引来引用int数组中的各个 s )。

最后的 for 循环将尝试打印数组的所有 10 个值。包括未初始化的值,#7 到 #9。这就是 valgrind 告诉你的。

valgrind 的诊断几乎无法解读,因为在您深入 I/O 库的内部之前,实际上不会发生未初始化的内存使用。错误在main()函数中,但它所做的只是将未初始化值的引用传递给 I/O 库。在 I/O 库中实际抓取未初始化的值以进行格式化之前,这不会触发未定义的行为。

PS:数组首先通过将数组的内容复制到新s数组来增长。原来arr的被删除并被新的 10 元素替换arr,然后五个值被复制回来s并被s删除。

这是很多不必要的复制。分配新的 10 元素数组,将现有内容复制到其中,然后删除原始数组,并用新数组替换它就足够了。


推荐阅读