【发布时间】:2022-01-08 05:28:52
【问题描述】:
标志 -O2 是什么意思?,因为我在使用标志 -O2 编译程序时收到信号 SIGSEGV,但如果我在 gcc 处删除该标志命令,程序运行完美,没有任何错误,我试图使用递归函数解决Primitive Calculator 问题,这只是一个递归和记忆问题。
然后使用这个命令程序可以完美运行......
gcc -pipe -std=c11 -g file.c
但是用这个另一个命令它不起作用,得到信号 SIGSEGV ... :'(
gcc -pipe -O2 -std=c11 -g file.c
例如,如果运行使用该标志(-O2)编译的程序,输入96234,我会收到此错误。
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/windowsky/Desktop/coursera/week5/a.out
96234
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551b2 in options (num=num@entry=21355, ptr=ptr@entry=0x7fffffffe7a8) at eje2.c:26
26
(gdb)
在那一点上它会因任何原因崩溃,正如我之前提到的,如果你删除标志 -O2 程序可以完美运行,我只想知道 -O2 标志在编译器中的含义,因为这并不对我有任何意义,我会失去理智。
那么这是代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
/* this is the type of operations that we can do */
enum opeType {
SUB_1,
DIV_2,
DIV_3
};
/* options: Recursive options */
int options (int num, int **ptr)
{
int minOperations, numOperations, i;
if (num <= 1)
return 0;
numOperations = 0;
minOperations= 2147483647;
for (i = 0; i < 3; ++i) {
switch (i) {
case DIV_2:
if (num % 2 == 0) {
if (*(*ptr + (num / 2)) == 0)
*(*ptr + (num / 2)) = options(num / 2, ptr) + 1;
numOperations = *(*ptr + (num / 2));
}
break;
case DIV_3:
if (num % 3 == 0) {
if (*(*ptr + (num / 3)) == 0)
*(*ptr + (num / 3)) = options(num / 3, ptr) + 1;
numOperations = *(*ptr + (num / 3));
}
break;
case SUB_1:
if (*(*ptr + (num -1)) == 0)
*(*ptr + (num - 1)) = options(num - 1, ptr) + 1;
numOperations = *(*ptr + (num - 1));
break;
}
if (numOperations < minOperations && numOperations != 0)
minOperations = numOperations;
}
return minOperations;
}
/* findingPath: This is the function that is going to find the path */
bool findingPath (int **ptr2, int num, int c)
{
int i;
bool flag;
if (num == 1)
return true;
else if (c >= 0) {
flag = false;
for (i = 2; i > -1; --i) {
switch (i) {
case SUB_1:
if (flag = findingPath(ptr2, num - 1, c - 1))
*(*ptr2 + c) = num - 1;
break;
case DIV_2:
if (num % 2 == 0 && (flag = findingPath(ptr2, num / 2, c - 1)))
*(*ptr2 + c) = num / 2;
break;
case DIV_3:
if (num % 3 == 0 && (flag = findingPath(ptr2, num / 3, c - 1)))
*(*ptr2 + c) = num / 3;
break;
}
if (flag)
return true;
}
}
return false;
}
/* one_test: Just one test */
void one_test ()
{
int num, *ptr, *ptr2;
int res, i;
num = 6;
ptr = (int *) malloc(sizeof(int) * (num + 1));
memset(ptr, 0, num);
res = options(num, &ptr);
assert(res == 2);
ptr2 = (int *) malloc(sizeof(int) * (res > 0 ? res : 1));
memset(ptr2, 0, res > 0 ? (res - 1) : 1);
findingPath(&ptr2, num, res > 0 ? (res - 1) : 1);
printf("%i\n", res);
for (i = 0; i < res; i++)
printf("%i ", *(ptr2 + i));
printf("%i ", num);
free(ptr);
free(ptr2);
ptr = NULL;
ptr2 = NULL;
}
/* manual_test: This is the manual test */
void manual_test ()
{
int num, *ptr, *ptr2;
int res, i;
scanf("%i", &num);
ptr = (int *) malloc(sizeof(int) * (num + 1));
memset(ptr, 0, num);
res = options(num, &ptr);
ptr2 = (int *) malloc(sizeof(int) * (res > 0 ? res : 1));
memset(ptr2, 0, res > 0 ? (res - 1) : 1);
findingPath(&ptr2, num, res > 0 ? (res - 1) : 1);
printf("%i\n", res);
for (i = 0; i < res; i++)
printf("%i ", *(ptr2 + i));
printf("%i ", num);
free(ptr);
free(ptr2);
ptr = NULL;
ptr2 = NULL;
}
void main ()
{
//one_test();
manual_test();
}
【问题讨论】:
-
优化经常暴露 UB。如果可能,请尝试使用
-fsanitize=address,undefined重新编译,如果不可能,请尝试在valgrind下运行。 -
实际上,您有几个警告,其中一个看起来很可疑。您应该至少使用
-Werror=all -Wextra进行编译,并尝试将其增加到-Werror=extra。然后开始寻找其他要启用的警告(我喜欢遵守-Werror=missing-declarations -Werror=redundant-decls,这有助于加强标题的完整性) -
options函数中有 very 深度递归。我输入了一个跟踪/深度参数,当该深度约为 16000 时我会崩溃。不确定 -O2 如何影响堆栈帧空间等,但也许考虑一个更好的方法来解决这个问题?
标签: c gcc segmentation-fault