C ++无法删除char *,不断破坏堆

时间:2013-12-31 02:07:12

标签: c++ delete-operator

语言:C ++,编译器:MSVS(/ Za)和g ++(是的,它必须适用于两者),级别:初学者

我正在尝试从char *中删除数据,以便我可以重新分配它并继续我的程序。我创建一个新的char *,为它分配命令行参数的值,进行一些验证,然后如果验证失败,它应该解除分配char *并让我为var分配新数据但是我得到了一个“堆”腐败检测到“视觉工作室的错误。我对我当前代码的修复以及任何其他可以更清晰/更简洁地完成的方式感到好奇。

在main()中:

//...
//make non constant versions to be messed with
char* ba = new char[ strlen(argv[4]) + 1 ];
char* num = new char[ strlen(argv[2]) + 1 ];

//make non constant versions of commandline stuff
nonConstant( argv[4], argv[2], ba, num );

//do the conversion and printing
convert( ba, num );
//...

转换是这样的:

//...
if( error ) {
    getNew(ba, num, &error);
}
//...

这里是getNew:

void getNew( char* ba, char* num, bool error ) {

//if there's an error in their numbers let them input new stuff and check to see if that's valid
while( error ) {
    //tell the user that the input was bad an prompt for more, use getline because strings are weird
    //cin stuff here (this part works, no problems)

    //free up base and num so I can reassign them
    delete[] ba; //<--this line fails
    delete[] num;

    //set lengths = to lengths of input + 1 for \0
    ba = new char[ inputBa.length() + 1 ];
    num = new char[ inputNum.length() + 1 ];

    //do the assignment of new input back to base and num
    inputBa.copy( ba, inputBa.length(), 0 );
    inputNum.copy( num, inputNum.length(), 0 );

    //ensure that the input was good this time
    validateInput( ba, num, error );
}

3 个答案:

答案 0 :(得分:3)

<强>停止!立即切换到std::string

这将修复您的代码,并根据要求更加清晰/简洁。

答案 1 :(得分:1)

如果您的getNew函数看起来可以重新分配本地banum所指向的内存,即delete[]它和new[]它。

但是ba中来电者numconvert呢?另外,ba中的nummain呢?它们按值传递给getNew,这意味着它们保持不变。他们继续指向他们原来的(现在死的)记忆位置。我猜你会继续在banum中使用那些现在毫无意义的convertmain值,直到它们导致崩溃。例如,如果您再次使用这些旧指针值调用getNewgetNew可能会在delete[]失败。

此外,还不能立即清楚errorconvert的内容。当&error实际需要getNew参数时,为什么要将它作为bool(可能是指针)传递?它会编译,但无论如何它看起来都是一个问题。

答案 2 :(得分:1)

通过char *&amp;传递参数将解决问题。

#include <stdio.h>
#include <string.h>

void reassgnReference( char * &ba, char * &num );
void reassgnPointerToPointer( char ** ba, char ** num );

int main( int argc, char ** argv )
{
    if ( argc > 4 )
    {
        char * ba = new char[strlen( argv[ 4 ] ) + 1];
        char * num = new char[strlen( argv[ 2 ] ) + 1];

        strncpy( ba, argv[ 4 ], strlen( argv[ 4 ] ) );
        strncpy( num, argv[ 2 ], strlen( argv[ 2 ] ) );

        printf( "In the beginning, ba = %s, num = %s\n", ba, num );

        reassgnReference( ba, num );
        printf( "reassgnReference(), ba = %s, num = %s\n", ba, num );

        reassgnPointerToPointer( &ba, &num );
        printf( "reassgnPointerToPointer(), ba = %s, num = %s\n", ba, num );
}
else
{
    printf( "%s Expects at least 4 arguments\n", argv[ 0 ] );
}

return( 0 );
}

void reassgnReference( char *& ba, char *& num )
{
    delete[] ba;
    delete[] num;

    char const * const newBa = "ba from reference";
    char const * const newNum = "num from reference";

    ba = new char[strlen( newBa ) + 1];
    num = new char[strlen( newNum ) + 1];

    strncpy( ba, newBa, strlen( newBa ) );
    strncpy( num, newNum, strlen( newNum ) );
}

void reassgnPointerToPointer( char ** ba, char ** num )
{ 
    delete[] *ba;
    delete[] *num;

    char const * const newBa = "ba from pointer to pointer";
    char const * const newNum = "num from pointer to pointer";

    *ba = new char[strlen( newBa ) + 1];
    *num = new char[strlen( newNum ) + 1];

    strncpy( *ba, newBa, strlen( newBa ) );
    strncpy( *num, newNum, strlen( newNum ) );
}