【问题标题】:C++ / Gcc - Stack smashing when a func returns a structC++ / Gcc - 函数返回结构时堆栈粉碎
【发布时间】:2025-12-12 18:55:03
【问题描述】:

我实际上在使用一个简单的程序时遇到了麻烦,该程序应该通过命名管道传递结构。

这是我的 main.cpp:

#include <cstdlib>                                                                                                   
#include <cstdio>
#include <iostream>
#include <string>
#include "NamedPipe.hh"

int             main()                                                                                               
{                                                                                                                    
  pid_t         pid;                                                                                                 
  std::string   str("test_namedPipe");                                                                               
  NamedPipe     pipe(str);                                                                                           
  message       *msg;                                                                                                

  //Initialisation of my struct                                                                                      
  msg = (message *)malloc(sizeof(message) + sizeof(char) * 12);                                                      
  msg->type = 1;                                                                                                     
  sprintf(msg->str, "Hello World");                                                                                  

  //Forking                                                                                                          
  pid = fork();                                                                                                      
  if (pid != 0) {                                                                                                    
    pipe.send(msg);                                                                                                  
  } else {                                                                                                           
    message msg_receive = pipe.receive(); //Here is the overflow                                                     
    std::cout << "type: " << msg_receive.type << " file: " << msg_receive.str << std::endl;                          
  }                                                                                                                  
  return (0);                                                                                                        
}

我的 NamedPipe.cpp:

#include "NamedPipe.hh"                                                                                              
#include <stdio.h>

NamedPipe::NamedPipe(std::string const &_name) : name("/tmp/" + _name) {                                             
  mkfifo(name.c_str(), 0666);                                                                                        
  // std::cout << "create fifo " << name << std::endl;                                                               
}

NamedPipe::~NamedPipe() {                                                                                            
  unlink(name.c_str());                                                                                              
}

void            NamedPipe::send(message *msg) {                                                                      
  int           fd;                                                                                                  
  int           size = sizeof(char) * 12 + sizeof(message);                                                          

  fd = open(name.c_str(), O_WRONLY);                                                                                 
  write(fd, &size, sizeof(int));                                                                                     
  write(fd, msg, (size_t)size);                                                                                      
  close(fd);                                                                                                         
}

message         NamedPipe::receive() {                                                                               
  int           fd;                                                                                                  
  int           size;                                                                                                
  message       msg;                                                                                                 

  fd = open(name.c_str(), O_RDONLY);                                                                                 
  read(fd, &size, sizeof(int));                                                                                      
  read(fd, &msg, (size_t)size);                                                                                      
  close(fd);                                                                                                         
  return (msg); //I debugged with printf. This actually reach this point before overflow                             
}

我的结构定义如下:

struct                          message {                                                                            
  int                           type;                                                                                
  char                          str[0];                                                                              
};

我实际上认为这可能是内存分配的问题,但我真的不知道该怎么做才能解决这个问题。

感谢阅读/帮助!

【问题讨论】:

  • 提示:assert(size&lt;sizeof(message))read(fd, &amp;msg, (size_t)size) 之前
  • 另外,你为什么在 C++ 中使用malloc 和原始指针?
  • 你是对的,我在这一点上遇到了一个错误......谢谢你的提示! (我其实是一个学习c++的c程序员)
  • 我会放弃str[0] 的思路,直到您真正理解该语言为止。这是先进的东西,很难做到正确。只需使用 std::vector&lt;unsigned char&gt; 代替字节缓冲区。
  • 本次培训的目的是通过命名管道发送一个包含 std::vector<:string> 和一个 int 的对象。我没有找到任何方法来发送整个对象并检索它,所以我尝试将它拆分为结构(消息)......

标签: c++ gcc struct stack


【解决方案1】:

这是你问题的根源,你的struct message

字符 str[0];

这在 C++ 中不是 kosher(在 C 中您使用它的方式也不是 kosher)。当您在堆栈上分配message 时,您正在为一个int 和0 个chars 分配空间。然后在这一行

read(fd, &msg, (size_t)size);

您将超出堆栈分配的内容写入梦幻岛。然后你返回你的message 对象,它的大小只有一个int

将您的结构更改为此,它应该“工作”

    struct message
    {
        int type;
        char str[ 16 ];
    };

【讨论】:

  • 这里的“Hello world”只是一个例子。我需要发送一些可变的 str 长度
  • 无论如何,你正在做的事情都行不通。这不是记忆的工作方式。我展示的内容将使您的示例代码不会占用所有内存,但您还需要在发送函数中调整大小计算。