函数接受结构指针和返回结构指针有奇怪的行为?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数接受结构指针和返回结构指针有奇怪的行为?相关的知识,希望对你有一定的参考价值。

我的代码我调用了insert函数,它传递一个指向struct(table)的指针,insert函数接收一个指针并执行一些操作并再次返回它。但是运行代码会导致分段错误。当我尝试使用传递的指针访问struct数组中的值。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define __USE_BSD
#include <string.h>

#include "speller.h"
#include "dict.h"

typedef struct 
{ // hash-table entry
  Key_Type element; // only data is the key itself
  enum {empty, in_use, deleted} state;
} cell;

typedef unsigned int Table_size; // type for size-of or index-into hash table

struct table 
{
  cell *cells; Table_size table_size; // cell cells [table_size];
  Table_size num_entries; // number of cells in_use
  // add anything else that you need
};

int hashfunc(Key_Type k, Table_size size)
{
    printf("enterd
");
    char * d = k;
    int hash = 0;
    int c;
    printf("%s
", d);
    printf("wtf??
");
    while (c = *d++)
    {
        printf("maybehere??
");
        hash = hash + c;
    }
    hash = hash%size;
    printf("%d
", hash);
    return hash;
}

Table initialize_table (Table_size size) 
{
    Table t = malloc(sizeof(struct table));
    t->table_size = size;
    cell hash_table[size];
    for (int i=0; i<size; i++)
    {
        hash_table[i].state = empty;
        hash_table[i].element = "-";
        //printf("initialised
");
    }
    t->num_entries = 0;
    t->cells = hash_table;
    /*for (int i = 0; i < t->table_size; i++)
    {
        printf("%d %s
", i, (t->cells + i)->element);
    }*/
    return t;
}

int a = 0;
Table insert (Key_Type k, Table t) 
{
    //printf("insert called %d
", a);
    printf("%d
", t->table_size);
    //printf("%s
", (t->cells + 2)->element);
    // as soon as program reaches here i get output like - 1 (NULL) 
    2 (NULL) and then segmentation fault
    for (int i = 0; i < t->table_size; i++)
    {
        printf("%d %s
", i, (t->cells + i)->element);
    }
    a++;
    printf("%s
", k);
    int hash_code = hashfunc(k, t->table_size);
    // Linear Probing
    printf("im here
");
    while(strcmp((t->cells + hash_code)->element,"-") != 0)
    {
        if (strcmp((t->cells + hash_code)->element,k) == 0)
        {
            printf("return at if
");
            return t;
        }
        else if (hash_code == (t->table_size - 1))
            hash_code = 0;
        else
            hash_code++;
    }
    (t->cells + hash_code)->element = k;
    (t->cells + hash_code)->state = in_use;
    t->num_entries += 1;
    printf("return at end with value %s
", k);
    printf("inserted value %s
", (t->cells + hash_code)->element);
    return t;

}

Boolean find (Key_Type k, Table t) 
{
    return FALSE;
}

void print_table (Table t) 
{
    Table_size size = t->table_size;
    for (int i = 0; i<size; i++)
    {
        if (strcmp((t->cells + i)->element,"-") != 0)
            printf("%d %s
", i, (t->cells + i)->element);
    }
}

void print_stats (Table t) 
{
}

void main()
{

    Table table;
    Table_size table_size = 19;
    int a = 5;
    Key_Type input[5] = {"a","b","ab","abc","abcd"};
    table= initialize_table (table_size);
    //printf("%s
", input[1]);
    while (a)
    {
        table= insert("a",table);
        a--;
    }
    printf("printing table
");
    print_table(table);
}

这是dict.h代码

typedef char* Key_Type;
typedef struct table* Table;    // allows different definitions of struct table

Table initialize_table ();      // allows different parameters
Table insert (Key_Type, Table);
Boolean find (Key_Type, Table);
void print_table (Table);
void print_stats (Table);

这是speller.h代码

typedef enum {FALSE, TRUE} Boolean;

extern int verbose; // used to control monitoring output
extern int mode;    // used to control your algorithm

extern char *prog_name; // used by check

void check (void *memory) ; // check result from strdup, malloc etc.

我相信我不明白指针在这个程序中是如何工作的。

答案

这是问题所在,

cell hash_table[size];

然后,你使t->cells指向hash_table,但hash_tableinitialize_table()函数中的局部变量,因此当函数返回时它被销毁/解除分配,并且在它返回后不再可访问。

你也应该在堆上分配它,就像这样

cell *hash_table;
hash_table = malloc(size * sizeof(*hash_table));
if (hash_table == NULL)
    return NULL; // Probably free `t' so that no memory leaks
                 // happen

访问在函数的堆栈帧中分配的这样的局部变量,在该函数返回之后是未定义的行为,问题可能发生在代码中的其他地方或者当访问指向解除分配的数据的指针时。

旁注

与命名一致,并且毫不含糊,你使用了一个奇怪的CamelCase和下划线组合,无论它是否奇怪都没关系,保留它并在整个代码中保留它 - 尊重你自己的风格。并称之为cell typedefCell

另外,总是检查malloc()的返回值,它返回错误(分配失败)时返回NULL,你应该编写代码,好像所有坏事都会发生,因为它们会发生。

最后,从来没有typedef指针。它没有任何帮助,它只是模糊了一个声明是指针的事实。

以上是关于函数接受结构指针和返回结构指针有奇怪的行为?的主要内容,如果未能解决你的问题,请参考以下文章

c语言中函数返回值可以是数组、字符串和结构体吗?

在结构中分配内存时出现不可预测的行为

C++指针问题,请问如何定义一个返回值为结构体指针数组的函数?

C语言返回结构指针的函数

使用双指针为结构成员赋值

go结构,结构嵌套,接口,指针的测试和结论