c - 为什么在此 C 代码中会发生堆栈粉碎?

标签 c stack

对于我在 C 语言中缺乏关于堆栈粉碎的知识,我提前表示歉意。 我在 ubuntu 12.04 上使用 Code::Blocks 进行编辑。 我编写了一个导致堆栈崩溃的简单 C 程序,但互联网搜索没有找到关于为什么会发生这种情况的有用建议。

示例 C 代码:

#include<stdio.h>

struct point3
    {float x, y, z;};

struct quadPolygon
    {struct point3 vert1, vert2, vert3, vert4;};

int writeLine(const char * objString)
    {FILE *file; file = fopen("aPlane.obj","a+"); fprintf(file,"%s",objString); fclose(file); return 0;};

int writeOBJ(struct quadPolygon myPoly)
    {
    char objString[] = "# plane def\n";  writeLine(objString);

    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

    char objStringSmooth[] = "s off\n";  writeLine(objStringSmooth);
    char objStringFace[] = "f 1 2 3 4\n";  writeLine(objStringFace);
    return 0;
    };

int main()
{
    struct quadPolygon myPoly1 =
    {
    .vert1.x=1.0, .vert1.y=-1.0, .vert1.z=0.0,
    .vert2.x=1.0, .vert2.y=1.0, .vert2.z=0.0,
    .vert3.x=-1.0, .vert3.y=1.0, .vert3.z=0.0,
    .vert4.x=-1.0, .vert4.y=-1.0, .vert4.z=0.0
    };
    writeOBJ(myPoly1);
    return 0;
};

为什么堆栈崩溃了,我该如何更改我的代码来避免这种情况?这与上面代码中错误使用指针有关吗?您可能会说,我对 C 有点陌生,但对其他语言有一些编程经验。

我读过“Stack Smashing 实际上是 gcc 用来检测缓冲区溢出攻击的一种保护机制”和“这意味着您以非法方式写入堆栈上的某些变量,很可能是 Buffer 的结果溢出”。

感谢您的任何回复/回答。

更新 - 根据 Evan 的评论,这里是修改后的有效代码。也许这可以帮助其他人。

#include<stdio.h>

struct point3
    {float x, y, z;};

struct quadPolygon
    {struct point3 vert1, vert2, vert3, vert4;};

int writeOBJ(struct quadPolygon myPoly)
    {
    FILE *file; file = fopen("aPlane.obj","a+");
    fprintf(file,"%s","# plane def\n");
    char objString[128];
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);
        fprintf(file,"%s",objString);
    char objStringSmooth[] = "s off\n";
        fprintf(file,"%s",objStringSmooth);
    char objStringFace[] = "f 1 2 3 4\n";
        fprintf(file,"%s",objStringFace);
    fclose(file);
    return 0;
    };

int main()
    {
    struct quadPolygon myPoly1 =
        {
        .vert1.x=1.0, .vert1.y=-1.0, .vert1.z=0.0,
        .vert2.x=1.0, .vert2.y=1.0, .vert2.z=0.0,
        .vert3.x=-1.0, .vert3.y=1.0, .vert3.z=0.0,
        .vert4.x=-1.0, .vert4.y=-1.0, .vert4.z=0.0
        };

    writeOBJ(myPoly1);
    return 0;
    };

再次感谢大家。

最佳答案

这就是你的问题所在:

char objString[] = "# plane def\n";  writeLine(objString);

snprintf(objString, 128, "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

objString 是一个包含 strlen("# plane def\n") + 1 个空格字符的数组。然后在传递 128(太大了)的缓冲区上使用 snprintf

我会这样重写:

writeLine("# plane def\n");

char objString[128]
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

要点:

为什么要为写入的每一 行打开和关闭文件?这是非常低效的......

最好在程序启动时打开文件一次,写入所有行,然后在完成时关闭它。这也将使代码更简单。

关于c - 为什么在此 C 代码中会发生堆栈粉碎?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10747007/

相关文章:

c - 使用 malloc 为 C 中的字符串分配内存

c - 读取寄存器的宏函数

c - 如何将 HFCLK 更改为由微处理器上的低频振荡器控制?

c - sizeof ('a' ) 和 sizeof ("a") 的区别

c - 静态、堆栈和堆分配有何不同?

r - R中的堆栈向量

c++ - 调用栈打印函数时死循环

c - 在 Korn shell 脚本中将斜杠替换为单词 'slash'

c++ - 删除链表末尾的节点C++

python - 使用堆栈的 Hanoi Python 解决方案的递归塔