在 C++ 中访问数组负索引处的内存不会返回垃圾
Accessing memory at negative indexes of array in C++ does not return garbage
我编写了以下程序来搜索给定字符串数组中的特定字符串。我在搜索函数中犯了一个错误,写了 i-- 而不是 i++。
#include <iostream>
#include <string>
using namespace std;
int search(string S[], int pos, string s)
{
for(int i=0; i<pos; i--) {
cout << i << " : " << S[i] << "n";
if (S[i] == s) {
cout << "Inside Return ->n";
cout << i << " / " << S[i] << " / " << s << "n";
return i;
}
}
return -1;
}
int main()
{
string S[] = {"abc", "def", "pqr", "xyz"};
string s = "def";
cout << search(S,2,s) << "n";
return 0;
}
从逻辑上讲,循环是一个无限循环,不应该停止,但我观察到的是每次搜索的 if 条件都为真,并且函数返回 -1。
我打印了这些值,并注意到 S[-1] 的值始终与传递给函数(要搜索的字符串(的第三个参数相同,因此循环每次都返回 -1。
这是 g++ 正在做的事情,还是与为函数的形式参数分配内存的方式有关?
输出上述代码 -
0 : abc
-1 : def
Inside Return ->
-1 / def / def
PS - 我正在使用 g++ (Ubuntu 7.3.0-27ubuntu1~18.04( 7.3.0
编辑 - 我知道 g++ 不检查边界,但我对 S[-1] 的值始终与 s 相同这一事实很感兴趣。我想知道是否有任何可能的理论
越界访问是未定义的行为。
未定义的行为不是"垃圾"或"段错误",它实际上是任何东西。 读取可能会进行时间旅行,并使程序早期的代码行为不同。 程序的行为,从头到尾,每当任何地方发生任何未定义的行为时,它完全不受C++标准的规定。
在这种情况下,朴素汇编和 ABI 会告诉您,运行时"堆栈"上的参数位于函数参数等内容旁边。
因此,将代码天真地重写为汇编会导致从参数读取到函数的负索引。
但是,将程序作为机器代码的无数完全无害,常见和安全的替代解释,从内联开始,远离那里,使这种情况不会发生。
在没有 LTO 或动态库边界的情况下进行编译时,您可以对编译器发布的 ABI 将用于进行调用有少量的信心;其他地方的任何假设都是危险的糟糕。 如果你在没有 LTO 的情况下进行编译并依赖它,这意味着你必须从现在开始直到永远审核代码的每个构建,否则冒着错误出现的风险,从现在开始很久没有明显原因。
- 在 C++ 中访问数组负索引处的内存不会返回垃圾
- 共享内存:MapViewOfFile 返回错误 5
- 将内存分配返回值强制转换为 TYPE 数组
- 在先前调用 string::find 后添加内存分配和内存集会导致它返回 npos.为什么?
- 为什么 free() 函数不将内存返回给操作系统?
- 从函数返回时C++内存管理
- 字符 * 未从重载运算符或内存管理问题正确返回
- 如何返回定义良好的内存部分?例如来自图像数据的像素的颜色值
- 函数,返回变量c++占用的内存位置的大小
- 指针地址的内存偶尔更改了函数前和后返回
- 内存浪费?如果main()应该只返回0或1,那么为什么main是用int而不是短int甚至char声明的
- Clang++ 6.0 内存清理器未报告返回值指示条件分支的函数中的未初始化局部变量
- CUDA 中的递归返回非法内存访问
- C++返回数组而不进行动态内存分配?
- Visual C 运行时:Malloc将指针返回到已经使用的内存(包含实际字符串)
- C++动态分配内存返回数组
- 崩溃或被迫退出后,C++动态分配的内存返回
- 检测到严重错误 c0000374 - C++ dll 将指针断开分配给 C# 的内存返回
- C++:从堆栈内存返回std::字符串引用
- 在不终止程序的情况下将动态分配的内存返回给操作系统