简体   繁体   English

未初始化和复制的指针变量的地址

[英]Address of an uninitialized and copied pointer variable

I am failed to understand this to deep details as to why program1 would segfault and program2 would not.我无法深入了解为什么 program1 会出现段错误而 program2 不会。

program1:程序1:

void cpy(char* p, char* q) {
  while(*p++ = *q++);
}

int main() {
  char* p;
  char* q = "Bhargava";
  cpy(p, q); 
  std::cout << "p = " << &p << std::endl;
}

Program2:程序2:

void cpy(char* p, char* q) {
  while(*p++ = *q++);
}

int main() {
  char* p;
  char* q = "Bhargava";
  cpy(p, q); 
  std::cout << "p = " << p << std::endl;
}

What is the harm while printing the address of the variable 'p' here in program1?在program1中打印变量'p'的地址有什么危害?

Both programs have undefined behavior already at the call两个程序在调用时都有未定义的行为

cpy(p, q);

because p is of type char* and default-initialized with automatic storage duration, meaning that its value is indeterminate .因为pchar*类型并且默认初始化并具有自动存储持续时间,这意味着它的值是indeterminate Copying an indeterminate value (here into the function parameter) that is not of type std::byte or unsigned narrow character type has already undefined behavior.复制非std::byte类型或无符号窄字符类型的不确定值(此处为 function 参数)已经具有未定义的行为。

The arithmetic on and dereferencing of this indeterminate value in cpy then continues to cause operations with undefined behavior, which is probably of more practical relevance than the undefined behavior mentioned above, given that it is clear that if p is considered to have some random value, accessing the memory at that random address should not be allowed by the operating system (the cause of a segmentation fault).然后在cpy中对这个不确定值的算术和取消引用继续导致具有未定义行为的操作,这可能比上面提到的未定义行为更具有实际相关性,因为很明显,如果p被认为具有一些随机值,操作系统不应允许在该随机地址访问 memory(导致分段错误)。

Undefined behavior means that you have no guarantee on the program behavior.未定义的行为意味着您无法保证程序的行为。 The program might fail with an error or it might not and it might produce seemingly correct output or it might not.该程序可能会因错误而失败,也可能不会,它可能会产生看似正确的 output ,也可能不会。

In practice, the compiler is probably optimizing away the dereferencing of p in one of the programs, but not the other, so that there never will be memory access in the compiled program that will cause the segmentation fault, but as mentioned above you have no guarantees and the compiler can output anything.在实践中,编译器可能正在优化其中一个程序中p的取消引用,而不是另一个程序,因此编译程序中永远不会有 memory 访问会导致分段错误,但如上所述,您没有保证和编译器可以 output 任何东西。


The line线

char* q = "Bhargava";

is not allowed since C++11 and should at least be producing a compiler diagnostic to that effect.自 C++11 以来是不允许的,并且至少应该为此产生编译器诊断。 Even before C++11, it was always deprecated in standard-C++.甚至在 C++11 之前,它在标准 C++ 中总是被弃用。 "Bhargava" has type const char[N] for some N , so it can be assigned to const char* , but not to char* . "Bhargava"对于某些N具有const char[N]类型,因此可以将其分配给const char* ,但不能分配给char* The latter was just allowed by the language initially for backwards-compatibility reasons with C.出于与 C 向后兼容的原因,该语言最初只允许后者。

Both programs exhibit Undefined Behavior because p is not pointing at any valid memory, its value is uninitialized and thus indeterminate , so calling cpy() with p as the destination will write to random memory, if not just crash outright.两个程序都表现出未定义的行为,因为p没有指向任何有效的 memory,它的值是未初始化的,因此是不确定的,因此以p作为目标调用cpy()将写入随机 memory,如果不只是彻底崩溃的话。

That being said, the reason why << &p works is because &p is the address of the p variable itself, which is a valid address.话虽这么说, << &p起作用的原因是因为&pp变量本身的地址,这是一个有效的地址。 The type that &p returns is char** , which operator<< does not have a specific overload for, but it does have an overload for void* , which char** is implicitly convertible to. &p返回的类型是char**operator<<没有特定的重载,但它确实有void*的重载, char**可以隐式转换为。 That overload simply prints out the address as-is.该重载只是按原样打印出地址。

The reason why << p does not work is because operator<< does have a specific overload for char* . << p不起作用的原因是因为operator<<确实对char*特定的重载。 That overload treats the address as the start of a C-style null-terminated string, and will print out characters starting at the address until a '\0' character is reached.该重载将地址视为 C 样式以空结尾的字符串的开头,并将打印出从地址开始的字符,直到到达'\0'字符。 But, since p does not point to a valid C string, the behavior is undefined .但是,由于p不指向有效的 C 字符串,因此行为是undefined

To make both programs work correctly, you need to do this instead:为了使这两个程序都能正常工作,您需要这样做:

Program1:程序1:

void cpy(char* p, const char* q) {
  while(*p++ = *q++);
}

int main() {
  char buffer[10];
  char* p = buffer;
  const char* q = "Bhargava";
  cpy(p, q); 
  std::cout << "p = " << &p << std::endl;
}

Program2:程序2:

void cpy(char* p, const char* q) {
  while(*p++ = *q++);
}

int main() {
  char buffer[10];
  char* p = buffer;
  const char* q = "Bhargava";
  cpy(p, q); 
  std::cout << "p = " << p << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM