【发布时间】:2021-05-21 22:29:08
【问题描述】:
我是编程新手。所以我不知道如何正确使用调试工具。 Xcode 告诉我“线程 1:EXC_BAD_ACCESS (code=1, address=0xffefbf3804)”。如果您能帮助我解决这个问题并修复错误,我将不胜感激。程序必须读取文件.bmp,然后我想计算像素亮度值并将它们放入数组[][]中并使用它们。
int main()
{
char* filename = (char*)("/…/second.bmp");
FILE* f = fopen(filename, "rb");
char info[54];
fread(info, sizeof(char), 54, f);
int width = *(int*)&info[18];
int height = *(int*)&info[22];
cout << " Name: " << filename << endl;
cout << " Width: " << width << endl;
cout << "Height: " << height << endl;
cout << endl;
int row_padded = (width * 3 + 3) & (~3);
unsigned char* data = new unsigned char[row_padded];
int array_bmp[height][width];
int arr_bmp[height][width];
for(int i = 0; i < height; i++)
{
fread(data, sizeof(char), row_padded, f);
for(int j = 0; j < width*3; j += 3)
{
// Y = 0.3 * R + 0.59 * G + 0.11 * B - яркость пикселя
// ============================
array_bmp[i][j] = 0.3 * (int)data[j+2] + 0.59 * (int)data[j+1] + 0.11 * (int)data[j]; // error message here
// ==========================
}
}
delete[] data;
fclose(f);
return 0;
}
【问题讨论】:
-
这里有很多令人担忧的问题,其中许多源于一种几乎病态的模式,即人人加狗。 不要。别这样了。你正在丢弃重要的类型信息。
const char* filename = "..."是正确的版本。抛弃const是个大问题。 -
int width = *(int*)&info[18];未定义的行为。如果您的 CPU 是在 21 世纪制造的,那么当您尝试访问未对齐的int时,它会告诉您迷路。您需要使用适当的工具来重铸这些。您不能只是将这些值强加到您预期的形式中。 -
"So I don't know how to properly use the debugging tools"-- 我强烈建议您阅读此内容:What is a debugger and how can it help me diagnose problems? 您可能还想阅读此内容:How to debug small programs?。 -
当我看到像
(char*)或reinterpret_cast这样的 C 风格演员表时,我的一般经验法则是仔细寻找错误。我的第一步通常是删除演员表并重建,看看编译器给了我什么有用的诊断。编译器是你的朋友,它给出的错误和警告是爱的标志。他们是编译器告诉你它不希望你浪费你的生命来修复简单的逻辑错误。 -
int array_bmp[height][width]; int arr_bmp[height][width];-- 请注意,这不是有效的 C++。 C++ 中的数组的大小必须由编译时常量而不是运行时变量来表示。即使这是有效的,如果height和/或width是大值,您也有耗尽堆栈内存的风险。相反,使用std::vector<std::vector<int>> array_bmp(height, std::vector<int>(width)); auto arr_bmp = array_bmp;,然后在满意时将其更改为使用单个维度std::vector<int> arr_bmp(height * width)并计算行/列位置。