Язык: 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 );
}
Передайте параметры с помощью 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 ) );
}
Прекрати ! Переключитесь на std::string
, немедленно.
Это будет как исправлять ваш код, так и быть более четким/кратким, по запросу.
std::string
само по себе мало что исправит. Это может остановить сбои, но не заставит код работать так, как задумано.
Если внешний вид, как ваша getNew
функция может перераспределить Запоминающее устройство локального ba
и num
указывают на, то есть delete[]
это и new[]
еще раз.
Но как насчет ba
и num
в вызывающем, в convert
? Кроме того, как насчет ba
и num
в main
? Они передаются getNew
по значению, что означает, что они остаются неизменными. Они продолжают указывать на их оригинальные (теперь мертвые) ячейки памяти. Я бы предположил, что вы продолжаете использовать эти бессмысленные значения ba
и num
в convert
и в main
до тех пор, пока они не приведут к сбою. Например, если вы getNew
с этими старыми значениями указателя, getNew
скорее всего не удастся при delete[]
.
Кроме того, не сразу понятно, какая error
в convert
. Почему вы передаете его как &error
(вероятно, указатель), когда getNew
самом деле ожидает аргумент bool
? Он будет компилироваться, но в любом случае это похоже на проблему.
&error
, я использую его как флаг в моей функции проверки, если где-то есть ошибка. Однако я понимал, что, отправляя char * вокруг, я не отправлял значение, а вместо этого передавал указатель на значение, что означало бы, что после изменения в одном месте оно изменяется во всех местах. Разве это не так? Если это не так, что мне нужно сделать, чтобы это было так?
char *
вы можете изменить указанное значение, и оно будет «меняться везде». Но если вы измените сам указатель , он не будет «меняться везде». Если вы хотите изменить указатель char *
в вызываемом объекте, а затем увидеть это изменение в вызывающем объекте, по той же логике вы должны по существу передать указатель на указатель ( char **
). Или в C ++ вы можете использовать ссылку на указатель для достижения того же эффекта. Ссылка на указатель объявляется как char *&
.
error
параметраgetNew
объявлена с типомbool
, почему соответствующий аргумент в вызовеgetNew
выглядит как&error
??? Я имею в виду, что это может быть формально правильно, так как указатели конвертируются в типbool
. Но все же, что за идея была здесь?