C ++ не может удалить char *, продолжает портить кучу

0

Язык: 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 an error in their numbers let them input new stuff and check to see if that 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 );
}
  • 0
    Включить подсказки и предупреждения при компиляции.
  • 1
    Если error параметра getNew объявлена с типом bool , почему соответствующий аргумент в вызове getNew выглядит как &error ??? Я имею в виду, что это может быть формально правильно, так как указатели конвертируются в тип bool . Но все же, что за идея была здесь?
Показать ещё 1 комментарий
Теги:
delete-operator

3 ответа

1
Лучший ответ

Передайте параметры с помощью char * и устраните проблему.

#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 ) );
}
  • 0
    Хотелось бы получить немного больше объяснений или ссылку на документацию / примеры, если это проще.
  • 0
    И это ничего не исправило, чтобы изменить это, хотя я действительно не знаю, почему это было бы лучше. Проведенное мной исследование показало, что если я перейду по ссылке, я не смогу переназначить ее, что я и пытаюсь сделать.
Показать ещё 2 комментария
3

Прекрати ! Переключитесь на std::string, немедленно.

Это будет как исправлять ваш код, так и быть более четким/кратким, по запросу.

  • 0
    Что ж, если проблема действительно в том, что OP не понимает семантику ссылок и значений (при передаче аргументов), то переключение на std::string само по себе мало что исправит. Это может остановить сбои, но не заставит код работать так, как задумано.
1

Если внешний вид, как ваша getNew функция может перераспределить Запоминающее устройство локального ba и num указывают на, то есть delete[] это и new[] еще раз.

Но как насчет ba и num в вызывающем, в convert? Кроме того, как насчет ba и num в main? Они передаются getNew по значению, что означает, что они остаются неизменными. Они продолжают указывать на их оригинальные (теперь мертвые) ячейки памяти. Я бы предположил, что вы продолжаете использовать эти бессмысленные значения ba и num в convert и в main до тех пор, пока они не приведут к сбою. Например, если вы getNew с этими старыми значениями указателя, getNew скорее всего не удастся при delete[].

Кроме того, не сразу понятно, какая error в convert. Почему вы передаете его как &error (вероятно, указатель), когда getNew самом деле ожидает аргумент bool? Он будет компилироваться, но в любом случае это похоже на проблему.

  • 0
    хорошая вещь на &error , я использую его как флаг в моей функции проверки, если где-то есть ошибка. Однако я понимал, что, отправляя char * вокруг, я не отправлял значение, а вместо этого передавал указатель на значение, что означало бы, что после изменения в одном месте оно изменяется во всех местах. Разве это не так? Если это не так, что мне нужно сделать, чтобы это было так?
  • 0
    @dlkulp: Да, передав указатель char * вы можете изменить указанное значение, и оно будет «меняться везде». Но если вы измените сам указатель , он не будет «меняться везде». Если вы хотите изменить указатель char * в вызываемом объекте, а затем увидеть это изменение в вызывающем объекте, по той же логике вы должны по существу передать указатель на указатель ( char ** ). Или в C ++ вы можете использовать ссылку на указатель для достижения того же эффекта. Ссылка на указатель объявляется как char *& .
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню