繁体   English   中英

通过指针索引到char数组时出现分段错误

[英]Segmentation fault when indexing into char array via pointer

我的代码在访问数组元素时导致分段错误,即使该元素已经被访问也没有问题。

int charToInt(char a)
{
    int b;
    if(isdigit(a))
    {   
        b = a - '0' - 1;
    }
    if(isalpha(a))
    {
        b = a - 65; 
    }
    return b;   
}

int validPosition(char **array, int r, int c, char* position, int slots)
{
    int i,k;
    if(strlen(position) == 5)
    {
        if(!isalpha(position[0]) || !isdigit(position[1]) || position[2]!=' ' || (position[3]!='N' && position[3]!='E' && position[3]!='W' && position[3]!='S')) //lathos gramma
        {
            printf("\n%s", "Invalid answear.This is an example of a valid answear: A5 N");
            return 2;
        }
        if( charToInt(position[0]) > r - 1 || charToInt(position[1]) > c - 1  )//ama vgainei eksw apo ta oria
        {
            printf("\n%s", "The position you choosed is out of the bountries...");
            return 2;
        }
        printf("\n%s%c%s","position[3] is: ",position[3], " but it doesn't work >_<"); // position[3] is N 
        if(position[3] == 'N') //the problem is here <~~~~~~~~~~~~~~~~~~~<
        {
            printf("\n%s", "come on");
            if(charToInt(position[0]) + slots < r)
            {
                for(i=charToInt(position[0])-1; i<charToInt(position[0])+slots; i++)
                {
                     if(array[i-1][charToInt(position[1])-1] != '.')
                     {
                         printf("\n%s", "The position you choosed is not valid because there is oneother ship there");
                         return 2;
                     }
                }
            }
            else
            {
                printf("\n%s", "The ship is going out of the bountries...");
                return 2;
            }
        }
    }
}

position包含字符串"A9 N"printf正确输出position[3] 'N' 由于某种原因,当尝试执行if(position[3] == 'N') ,会发生分段错误。

示例程序运行:

Example of positioning: G3 E

Aircraft carrier (5 places), Give location and direction: A9 N

1

position[3] is: N but it doesn't work >_<

好吧,根据您的更新,看来您有很多问题。 为了将来参考,实际上添加(可能是简化的)代码来显示您如何调用所讨论的函数比尝试在评论中使用prose来描述它更好。 试图帮助您的人们的猜测会更少。

如果我正确阅读了您的评论,则调用validPosition的代码如下所示:

// "r and c are 9 and 9 in the specific example(rows columns)."
int rows = 9;
int columns = 9;

// "slots=5."
int slots = 5;

// "array is a 2d array and it contains characters(created with malloc)."
char **array = malloc(rows * columns * sizeof(char));

// "i created char position[10] in the function that called this function"
char position[10];
// "and with fgets(position, 10, stdin); i putted A9 N inside it."
fgets(position, 10, stdin);

validPosition(array, rows, columns, position, slots);

第一个问题是您对数组分配的描述(如果我误解了您的评论,而这实际上不是您的工作,我深感抱歉)。 对于具有两个下标操作( array[index1][index2] ,因为它在validPosition )使用的动态大小的二维数组,它的外观应类似于以下代码。 以这种方式访问​​指针到指针( char **array )的作用与固定大小的多维数组( array[SIZE1][SIZE2] )不同。

// each entry in array should be a pointer to an array of char
char **array = malloc(rows * sizeof(char*));
for(i = 0; i < rows; i++)
    array[i] = malloc(columns * sizeof(char));

您还需要在fgets调用后使用位置小心。 您应该检查返回值以确保它不为NULL (指示EOF或错误情况)。 在这种情况下,字符串不能以\\0结尾。 实际上,所有元素可能仍未初始化(假设您未在调用之前初始化它们)。 这可能导致不确定的行为。

下一个问题是, validPosition不会在每个代码路径上返回一个值。 一个示例是strlen(position) != 5 另一个是如果您输入for循环并且array[i-1][charToInt(position[1])-1] != '.' 永远都不是真的(也就是说,船舶安置被认为是有效的)。

对于说英语的希腊人作家来说,这很奇怪,让我们忽略国际化而只关注默认的C local。 尽管可以考虑允许用户也使用小写字母,但是对position [0]的检查应该足够了。 当转换position[1]1系到0系,但是,不考虑的情况下,当它是'0' ,这将导致在charToInt返回-1 此外,您错误地在array[i-1][charToInt(position[1])-1]的第二个数组下标中再次进行了减法。

同样,正如Jite和BLUEPIXY指出的那样,您正在对charToInt(position[0])的结果进行两次额外的减法:一次在for循环初始化程序中( i=charToInt(position[0])-1 )在另一次array[i-1][charToInt(position[1])-1]的第一个数组下标。

解决此问题后,您可能会发现有时有时会错误地告诉用户其选择无效。 这是因为您正在检查charToInt(position[0]) + slots < r而不是<= r

正如我在评论中提到的,对array的访问之一很可能是您的细分违规行为的元凶,而不是position[3] == 'N' 您看不到printf("\\n%s", "come on");的输出的原因printf("\\n%s", "come on"); 是您的stdout似乎是行缓冲的,没有行尾可以刷新它。 通常,它会在正常程序终止时自动刷新,但是您会出现段错误,因此不会发生。

最后,这些只是我注意到的语义错误。 从风格上讲,该代码也可以改进。 例如,似乎您将要实现else if(position[3] == 'E'else if(position[3] == 'W' ,以及else if(position[3] == 'S'子句具有与if(position[3] == 'N'子句类似的逻辑。这增加了您通过错误地复制粘贴而引入错误的可能性,并且在以后需要进行更改时增加了工作量在四个地方而不是一个地方。

自从术语“分段故障”以来,我相信您在Linux计算机上。 使用gdb查找错误原因。 步骤如下。

  1. 使用其他-g标志进行编译(例如gcc -g my_prog.c)
  2. 运行调试器:gdb a.out
  3. 使用“列表”命令查找断点行(例如,函数的第一行)
  4. 使用以下命令在该行上设置断点:b 25(如果该行为25)
  5. 使用“运行”命令运行程序
  6. 使用命令“ next”执行下一行代码

现在执行将在该行暂停,您可以检查内存,打印变量内容和内容。 但通常您要确定执行失败的行以及变量中的内容。

只需一点点的记忆,您就可以轻松找到问题所在。 就个人而言,我的代码无法与gdb支持一起使用。

array[i-1][charToInt(position[1])-1]分割错误

i: charToInt(position[0])-1 :charToInt('A')-1:-1 <-数组越界

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM