离开循环时的矢量数据丢失

时间:2016-09-12 14:18:14

标签: c++ memory vector allocation

我不会认为自己是一个编程新手,但我现在一直在努力了解矢量六个月的大部分时间。

我试图在"生产"中使用矢量。代码,但似乎永远不会发挥我的期望。这个例子是我遇到的许多问题之一,如标题中所述,在离开while循环后,Vector似乎神秘地丢失了数据。这可能归结为我只是简单地使用向量错误,但我想我的过程至少有点健全。正如您将注意到的,这是一个对象的向量,这也可能是该问题的关键。

在这个我做过的例子中,一个带有随机字符的char指针被添加到向量中,正好十次。每次都会删除char指针的内容并添加新内容以确保数据是唯一的。离开循环后,从另一个开始打印出向量的内容,刚刚添加到向量中的数据都不存在。为什么?

此外,从我看过的例子中,矢量的初始化是非标准的,但似乎是让矢量在没有崩溃的情况下工作的唯一方法。

为我糟糕的格式化道歉,代码块中的样式并不完全是我格式化代码的方式(支架间距略微搞砸了)提前感谢!

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



int main( int argc, char * argv[ ] ) {

    std::vector<char *> avector( 0 );
    avector.reserve( 400 );
    int counter = 0;
    char * place;
    bool ok;

    Back:
    if( counter == 10 ) {
        counter = 0;
        while( counter != 10 ){
            printf( "Element %d: %s\n", counter,  avector.at( counter ) );
            ++counter
        }
        ok = false;
    }
    while( counter != 10 ) {
        ok = true;
        place = (char *)malloc( 10 * sizeof( char ) );
        *place = (char)( ( rand( ) % 26 ) + 65 );
        printf("Pre-placement, element %d: %s\n", counter, place );
        avector.push_back( place );
        printf("Post-placement element %d: %s\n", counter, avector.at( counter ) );
        free( place );
        ++counter;

    }
    if( ok == true ) {
        goto Back;
    }


    exit( 0 );
}

2 个答案:

答案 0 :(得分:4)

place = (char *)malloc( 10 * sizeof( char ) );
您正在使用malloc

分配数据

avector.push_back( place );
你正在把它推到矢量

free( place );
然后,你删除它。因此,指针仍在向量中,但内存地址不再属于您。

此外,您使用的是C ++编程,而不是C编程,所以不要使用printf,goto,malloc和free。
并尝试不使用new和delete,而是使用智能指针(C ++ 11)

答案 1 :(得分:2)

代码中的主要错误是您正在添加指向矢量的指针,但随后使存储在其中的指针无效。

place = (char *)malloc( 10 * sizeof( char ) );
avector.push_back( place );
free( place );   // <<--- BUG; you destroyed what's pointed to by place

错误是placeplace中添加avector的位置(例如,avector[avector.size() - 1])都指向相同的内存位置,因此free place freeavector[avector.size() - 1]在给定的循环迭代中#include <iostream> #include <vector> using namespace std; int main( int argc, char * argv[ ] ) { vector<char *> my_char_pointers; cout << "Filling up vector ..." << endl; for(int i = 0; i < 5; ++i) { cout << "Adding address of " << char(65 + i) << " to vector ..." << endl; my_char_pointers.push_back(new char(65 + i)); } cout << "Printing vector ..." << endl; for(int i = 0; i < my_char_pointers.size(); ++i) cout << my_char_pointers.at(i) << endl; cout << "Deleting char pointer vector elements ..." << endl; for(int i = 0; i < my_char_pointers.size(); ++i) delete my_char_pointers[i]; cout << "Printing vector of now-INVALID pointers ..." << endl; for(int i = 0; i < my_char_pointers.size(); ++i) cout << my_char_pointers.at(i) << endl; cout << "Removing the now invalid pointers from vector ..." << endl; my_char_pointers.clear(); return 0; } 相同。

你基本上是从自己的脚下拉下地毯。

我认为一个更简单的例子可以帮助你更清楚地看到。这是您的代码的重构版本,使用适当的C ++而不是C ++和C的混合:

$ g++ -o test test.cpp
$ ./test 
Filling up vector ...
Adding address of A to vector ...
Adding address of B to vector ...
Adding address of C to vector ...
Adding address of D to vector ...
Adding address of E to vector ...
Printing vector ...
A
B
C
D
E
Deleting char pointer vector elements ...
Printing vector of now-INVALID pointers ...

 ��
`��
@��
���
Removing the now invalid pointers from vector ...

在我的Linux PC上运行它,您将获得以下输出:

delete

您的版本与我的版本之间需要注意一些差异,包括错误修复和其他细节:

  1. 我创建,但不要vector,同一循环内的new输入(这是修复);
  2. 您的代码难以理解,使错误更难以捕获/调试;
  3. 它使用deletemalloc,这是在C ++中分配/释放内存的正确方法(cout,朋友是C)
  4. 它使用<iostream>中的printf,这是用C ++打印输出的正确方法(goto用于C)
  5. 它使用结构合理的代码并且依赖于vector [1],这会导致意大利面条代码;
  6. 我的代码更容易理解,使任何错误更易于查找/修复
  7. 如果你真的想要成为一个&#34;编程新手&#34;你需要处理你的代码结构,简化的逻辑和其他细节。

    另请注意,您确实没有char个&#34;对象&#34 ;;你有一个指针vector s 的向量。名为my_char_pointers的{​​{1}}是一个对象,但其内容是 primitive 类型。 (是的,术语确实有所作为。)

    [1]为什么在Dijkstra的名字上会使用goto语句?它们会让你自己和那些将来不可避免地需要阅读你的代码的人感到很头疼。