我也是C ++编程的新手。当我在编写有关通过字符指针数组传递参数的代码时。我遇到了一个问题,其中某些操作后指针的值发生了变化。下面是我的代码。
#include <iostream>
using namespace std;
void input(char* argv[], int &i)
{
char buff[10][20]; //buffer string array
while (cin.peek() != '\n') {
cin >> buff[i++];
}
for (int j = 0; j < i; j++) {
argv[j] = buff[j];
}
argv[i] = NULL; // putting a NULL at the end
}
int main(int argc, char* argv[])
{
char *arg[10];
int i = 0;
input(arg, i); //input the arguments
for (int j = 0; j < i; j++) {
cout << arg[j] << endl; //output the arguments entered
}
return 0;
}
应该使用子功能void input(char* argv[], int &i)
输入我的参数多达9次,或者按Enter键时。 i
表示参数总数。
然后将参数存储为字符指针数组,然后将其传递回主函数的char *arg[10]
进行保存。
但是,我发现
cout << arg[j] << endl;
arg
的值丢失,正在打印随机值。
答案 0 :(得分:9)
您正在堆栈上创建一个二维字符数组buff
,然后通过argv
参数将指针返回到该数组中。但是buff
存在于堆栈中,并且在input
函数退出后就不复存在。 buff
占用的内存将被调用input
后调用的其他函数覆盖。
您应该在buff
中分配main
,然后将其传递到input
中,以便在main
返回之后,它继续存在于input
的范围内。 / p>
另一种选择是为buff
中的input
分配堆空间。在这种情况下,main
函数将负责在完成处理后释放内存。
很显然,您可以使用更高级的C ++功能来避免其中的一些开销。尽管这是一个C ++程序,但实际上是用C编写的。但是,了解内存和指针的工作方式对于理解最新的C ++功能解决的问题至关重要。
答案 1 :(得分:1)
我的指针的值改变了
指针是唯一不会损坏的东西。问题是他们指向到的内存。
您可以通过打印每个指针的值或仅在调试器中检查它们来证明第一部分。 (您可以通过强制转换为void来打印地址,而不是它指向的C字符串,例如cout << static_cast<void*>(arg[j]) << '\n'
。)
那么您的C字符串发生了什么?好吧,您在函数input
中声明了一个自动作用域数组变量。当函数退出时,该数组将不复存在,就像其他任何自动作用域变量一样。在变量不再存在之后,访问曾经用于生存的变量的内存是非法的。
在数组本身超出范围后,您将指针返回到该数组的事实并不意味着读取(取消引用)它们是合法的,这实际上是未定义的行为。
被覆盖的内容实际上是 best 案例,因为这意味着您已经注意到该错误:在提交/部署/出售之后,该错误可能合法地崩溃了,或更糟糕的是,它似乎可以正常工作。该程序,此后每次运行都崩溃。
答案 2 :(得分:0)
将堆栈视为大量(但不是无限)的内存。只需上下移动stack pointer
(方向将取决于硬件)就可以分配和释放它。
这是带有注释的代码。
input(arg, i);
// when you get here the stack pointer will have been moved up, freeing the space
// that was allocated for 'buf' in 'input'
// the space for 'j' could overwrite the space where 'buf' was
for (int j = 0; j < i; j++) {
// the calls to 'cout' and 'end;' could overwrite the space where 'buf was'
cout << arg[j] << endl;
}