【问题标题】:Getting a Bus Error when using memset() in C?在 C 中使用 memset() 时出现总线错误?
【发布时间】:2015-10-30 07:00:39
【问题描述】:

我正在制作一个使用共享内存和 mmap 在不同进程/线程之间进行通信的程序,但我在运行时不断收到总线错误。我已经隔离了错误,它似乎发生在 memset() 执行后。我是否错误地设置了内存映射? unsigned char *create_bitmap(unsigned long max)

 92 unsigned char *create_bitmap(unsigned long max)
 93 {
 94     int fd;
 95     unsigned long object_size = (max + 1) * sizeof(unsigned char);
 96     unsigned char *address;
 97
 98 //  fd = open("/dev/zero",O_RDWR);
 99     fd = shm_open("./morriluk_bitmap", O_RDWR|O_CREAT , S_IRUSR|S_IWUSR );
100     if(fd == -1){
101         perror("Unable to open morriluk_bitmap");
102         exit(EXIT_FAILURE);
103     }
104     printf("1\n");
105     if(ftruncate(fd, object_size) == -1){
106         perror("Unable to resize morriluk_bitmap");
107         exit(EXIT_FAILURE);
108     }
109     printf("2\n");
110
111     address = (unsigned char*)mmap(NULL, object_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
112     if (address == MAP_FAILED) {
113         perror("Unable to mmap morriluk_bitmap to any address");
114         exit(EXIT_FAILURE);
115     }
116     printf("3\n");
117
118     memset((void *)address, PRIME, object_size);
119     printf("4\n");
120
121     return address;
122 }

命令行输出:

creating bitmap
1
2
3
Bus error (core dumped)

【问题讨论】:

  • 调用create_bitmap()时,“max”的值是多少?关于 SO 有一些类似的问题,例如这个问题,表明一个可能的原因是缓冲区大小不正确:stackoverflow.com/questions/31056508/…
  • max 的值是由limit.h 设置的值UINT_MAX。我认为数值大约是 4,294,967,295。此外,似乎这种总线错误仅在“max”很大时发生。我在设置为 1000 时尝试过,效果很好。
  • 您使用的是 32 位操作系统还是 64 位操作系统?我不认为使用 LInux 32 位时你可以映射超过 3GB 的内存部分,并且 UINT_MAX 的值为 4GB-1。
  • uname -a 返回:Linux os-class.engr.oregonstate.edu 2.6.32-504.23.4.el6.x86_64 #1 SMP Tue Jun 9 20:57:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux 我认为这是 64 位。这是用于学校作业的学校服务器,所以我怀疑服务器无法处理它。
  • "对于可移植使用,共享内存对象应由 /somename 形式的名称标识;即,最多 NAME_MAX(即 255)个字符的以 null 结尾的字符串,由初始斜线,后跟一个或多个字符,其中没有一个是斜线。" (Linux shm_open(3) 手册页)。您提供的名称不符合这些条件。

标签: c shared-memory mmap memset bus-error


【解决方案1】:

我会告诉你一个你应该做的事情,那就是刷新和同步输出缓冲区。很可能您正在实际打印4,但由于崩溃而丢失了。

换句话说,无论你有什么:

printf("something");

改成:

printf("something"); fflush(stdout); fsync(fileno(stdout));

这将确保缓冲区被刷新,因为如果在您崩溃时没有刷新,您很可能会丢失信息。 fsync() 本身可能不是必需的,我使用它只是为了安全。

【讨论】:

  • 我已经刷新了输出缓冲区,但错误仍然发生在同一位置,memset()。我尝试注释掉memset() 并手动访问地图,每当我尝试访问大于UINT_MAX/4 的任何索引时,都会出现总线错误。任何想法可能导致此错误?这是否意味着我的地图不够大?我尝试使用更大的 object_size 并在完全相同的索引处得到完全相同的错误
猜你喜欢
  • 2014-05-20
  • 2011-03-23
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 2012-09-10
  • 1970-01-01
相关资源
最近更新 更多