为什么我在 Kali VM 中不断中止(核心转储)?
why I keep getting Aborted (core dumped) in Kali VM?
我正在做一个项目 C 中的项目,它的重点是创建一个多线程并与它们一起工作......
问题是该程序在我的 Mac 上运行良好,但是当我尝试处理项目时,Kali VM 或 WSL(Windows 子系统 Linux)。同样的代码给了我以下错误
kali VM 错误
└─$ ./a.out 3 800 200 200 1200 134 ⨯
malloc(): corrupted top size
zsh: abort ./a.out 3 800 200 200 1200
WSL上的错误
└─$ ./a.out 2 60 60 20
malloc(): corrupted top size
Aborted (core dumped)
您可以在此处查看完整代码 in this repo。
这是代码的主要文件:
#include "philosophers.h"
int ft_error_put(char *messsage, int ret)
{
printf("%s\n", messsage);
return (ret);
}
int ft_parsing(char **av, t_simulation *simulation)
{
int num;
int i;
int j;
i = 1;
j = 0;
while (av[i])
{
j = 0;
num = 0;
while (av[i][j])
{
if (av[i][j] >= '0' && av[i][j] <= '9')
num = num * 10 + (av[i][j] - '0');
else
return (ft_error_put("Error: Number Only", 1));
j++;
}
if (i == 1)
{
simulation->philo_numbers = num;
simulation->forks = num;
simulation->threads = (pthread_t *)malloc(sizeof(pthread_t) * num);
}
else if (i == 2)
simulation->time_to_die = num;
else if (i == 3)
simulation->time_to_eat = num;
else if (i == 4)
simulation->time_to_sleep = num;
else if (i == 5)
simulation->eat_counter = num;
i++;
}
if (i == 5)
simulation->eat_counter = -1;
return (0);
}
void ft_for_each_philo(t_simulation *simulation, t_philo *philo, int i)
{
philo[i].index = i + 1;
philo[i].left_hand = i;
philo[i].right_hand = (i + 1) % simulation->philo_numbers;
philo[i].is_dead = NO;
if (simulation->eat_counter == -1)
philo[i].eat_counter = -1;
else
philo[i].eat_counter = simulation->eat_counter;
}
t_philo *ft_philo_init(t_simulation *simulation)
{
t_philo *philo;
int i;
i = -1;
philo = (t_philo *)malloc(sizeof(t_philo));
while (++i < simulation->philo_numbers)
ft_for_each_philo(simulation, philo, i);
return (philo);
}
void *ft_routine(void *arg)
{
t_philo *philo;
philo = (t_philo *)arg;
printf("thread number %d has started\n", philo->index);
sleep(1);
printf("thread number %d has ended\n", philo->index);
return (NULL);
}
int main(int ac, char **av)
{
int i;
t_simulation simulation;
t_philo *philo;
i = 0;
if (ac == 5 || ac == 6)
{
if (ft_parsing(av, &simulation))
return (1);
philo = ft_philo_init(&simulation);
while (i < simulation.philo_numbers)
{
simulation.philo_index = i;
pthread_create(simulation.threads + i, NULL,
ft_routine, philo + i);
i++;
}
i = 0;
while (i < simulation.philo_numbers)
{
pthread_join(simulation.threads[i], NULL);
i++;
}
}
return (0);
}
您的程序在 pthread_create
调用时中止。
但是,问题是在 ft_philo_init
之前的 malloc
调用太短了。
您只为 一个 t_philo
结构分配了足够的 space 而不是 philo_numbers
旁注: 不要转换 malloc
的 return 值。参见:Do I cast the result of malloc?
这是更正后的函数:
t_philo *
ft_philo_init(t_simulation *simulation)
{
t_philo *philo;
int i;
i = -1;
// NOTE/BUG: not enough elements allocated
#if 0
philo = (t_philo *) malloc(sizeof(t_philo));
#else
philo = malloc(sizeof(*philo) * simulation->philo_numbers);
#endif
while (++i < simulation->philo_numbers)
ft_for_each_philo(simulation, philo, i);
return philo;
}
更新:
thank you it's worked now, but can you explain why it work on macOS but it doesn't in kali? – DarkSide77
嗯,它在 macOS 上不“工作”...
当我们对数组进行索引并超出 数组的边界时,它是 UB(“未定义行为”)。 UB 的意思就是:未定义 行为。
参见:
- Undefined, unspecified and implementation-defined behavior
- Is accessing a global array outside its bound undefined behavior?
任何事情 都可能发生。那是因为philo
数组占用了一定的内存。那个分配之后是什么?假设 philo
是 8 个字节 [或元素,如果你愿意——没关系]:
| philo[8] | whatever |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
只要我们保持在界限内,一切都很好(例如):
for (i = 0; i < 8; ++i)
philo[i] = 23;
如果我们超越终点,我们有 UB(例如):
for (i = 0; i < 9; ++i)
philo[i] = 23;
这里我们更进一步,修改了 whatever
的第一个单元格。
根据链接器放置的变量,可能有几种行为:
- 程序 似乎 到 运行 正常。
whatever
处的一个值已损坏,程序 运行s 但产生了不正确的结果。
whatever
与写保护的页面对齐。该程序将立即出现保护异常。
- 在
whatever
处损坏的值没有 即时 效果,但稍后程序会检测到损坏。
- 损坏最终会导致段错误,因为指针值已损坏。
在两个系统上,您的程序都在做同样的事情。对于我们从 malloc
获得的区域,whatever
是堆管理器用来跟踪分配的内部 struct
。该程序正在破坏它。
在 macOS
上,堆管理器没有检测到这一点。在 linux(glibc
),堆管理器做了更好的交叉检查并检测到损坏。
我正在做一个项目 C 中的项目,它的重点是创建一个多线程并与它们一起工作...... 问题是该程序在我的 Mac 上运行良好,但是当我尝试处理项目时,Kali VM 或 WSL(Windows 子系统 Linux)。同样的代码给了我以下错误
kali VM 错误
└─$ ./a.out 3 800 200 200 1200 134 ⨯
malloc(): corrupted top size
zsh: abort ./a.out 3 800 200 200 1200
WSL上的错误
└─$ ./a.out 2 60 60 20
malloc(): corrupted top size
Aborted (core dumped)
您可以在此处查看完整代码 in this repo。
这是代码的主要文件:
#include "philosophers.h"
int ft_error_put(char *messsage, int ret)
{
printf("%s\n", messsage);
return (ret);
}
int ft_parsing(char **av, t_simulation *simulation)
{
int num;
int i;
int j;
i = 1;
j = 0;
while (av[i])
{
j = 0;
num = 0;
while (av[i][j])
{
if (av[i][j] >= '0' && av[i][j] <= '9')
num = num * 10 + (av[i][j] - '0');
else
return (ft_error_put("Error: Number Only", 1));
j++;
}
if (i == 1)
{
simulation->philo_numbers = num;
simulation->forks = num;
simulation->threads = (pthread_t *)malloc(sizeof(pthread_t) * num);
}
else if (i == 2)
simulation->time_to_die = num;
else if (i == 3)
simulation->time_to_eat = num;
else if (i == 4)
simulation->time_to_sleep = num;
else if (i == 5)
simulation->eat_counter = num;
i++;
}
if (i == 5)
simulation->eat_counter = -1;
return (0);
}
void ft_for_each_philo(t_simulation *simulation, t_philo *philo, int i)
{
philo[i].index = i + 1;
philo[i].left_hand = i;
philo[i].right_hand = (i + 1) % simulation->philo_numbers;
philo[i].is_dead = NO;
if (simulation->eat_counter == -1)
philo[i].eat_counter = -1;
else
philo[i].eat_counter = simulation->eat_counter;
}
t_philo *ft_philo_init(t_simulation *simulation)
{
t_philo *philo;
int i;
i = -1;
philo = (t_philo *)malloc(sizeof(t_philo));
while (++i < simulation->philo_numbers)
ft_for_each_philo(simulation, philo, i);
return (philo);
}
void *ft_routine(void *arg)
{
t_philo *philo;
philo = (t_philo *)arg;
printf("thread number %d has started\n", philo->index);
sleep(1);
printf("thread number %d has ended\n", philo->index);
return (NULL);
}
int main(int ac, char **av)
{
int i;
t_simulation simulation;
t_philo *philo;
i = 0;
if (ac == 5 || ac == 6)
{
if (ft_parsing(av, &simulation))
return (1);
philo = ft_philo_init(&simulation);
while (i < simulation.philo_numbers)
{
simulation.philo_index = i;
pthread_create(simulation.threads + i, NULL,
ft_routine, philo + i);
i++;
}
i = 0;
while (i < simulation.philo_numbers)
{
pthread_join(simulation.threads[i], NULL);
i++;
}
}
return (0);
}
您的程序在 pthread_create
调用时中止。
但是,问题是在 ft_philo_init
之前的 malloc
调用太短了。
您只为 一个 t_philo
结构分配了足够的 space 而不是 philo_numbers
旁注: 不要转换 malloc
的 return 值。参见:Do I cast the result of malloc?
这是更正后的函数:
t_philo *
ft_philo_init(t_simulation *simulation)
{
t_philo *philo;
int i;
i = -1;
// NOTE/BUG: not enough elements allocated
#if 0
philo = (t_philo *) malloc(sizeof(t_philo));
#else
philo = malloc(sizeof(*philo) * simulation->philo_numbers);
#endif
while (++i < simulation->philo_numbers)
ft_for_each_philo(simulation, philo, i);
return philo;
}
更新:
thank you it's worked now, but can you explain why it work on macOS but it doesn't in kali? – DarkSide77
嗯,它在 macOS 上不“工作”...
当我们对数组进行索引并超出 数组的边界时,它是 UB(“未定义行为”)。 UB 的意思就是:未定义 行为。
参见:
- Undefined, unspecified and implementation-defined behavior
- Is accessing a global array outside its bound undefined behavior?
任何事情 都可能发生。那是因为philo
数组占用了一定的内存。那个分配之后是什么?假设 philo
是 8 个字节 [或元素,如果你愿意——没关系]:
| philo[8] | whatever |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
只要我们保持在界限内,一切都很好(例如):
for (i = 0; i < 8; ++i)
philo[i] = 23;
如果我们超越终点,我们有 UB(例如):
for (i = 0; i < 9; ++i)
philo[i] = 23;
这里我们更进一步,修改了 whatever
的第一个单元格。
根据链接器放置的变量,可能有几种行为:
- 程序 似乎 到 运行 正常。
whatever
处的一个值已损坏,程序 运行s 但产生了不正确的结果。whatever
与写保护的页面对齐。该程序将立即出现保护异常。- 在
whatever
处损坏的值没有 即时 效果,但稍后程序会检测到损坏。 - 损坏最终会导致段错误,因为指针值已损坏。
在两个系统上,您的程序都在做同样的事情。对于我们从 malloc
获得的区域,whatever
是堆管理器用来跟踪分配的内部 struct
。该程序正在破坏它。
在 macOS
上,堆管理器没有检测到这一点。在 linux(glibc
),堆管理器做了更好的交叉检查并检测到损坏。