简体   繁体   English

以下代码中的分段错误 11。 如何避免溢出?

[英]Segmentation fault 11 in following code. How to avoid overflow?

void main(int argc, char* argv[]) {

    char* hostname = (char*)malloc(sizeof(char)*1024);
    hostname = getClientHostName("122.205.26.34");
    printf("%s\n", hostname);
    free(hostname);
}

char* getClientHostName(char* client_ip) {

    char hostnames[5][2];
    hostnames[0][0] = "122.205.26.34";
    hostnames[0][1] = "aaaaa";
    hostnames[1][0] = "120.205.36.30";
    hostnames[1][1] = "bbbbb";
    hostnames[2][0] = "120.205.16.36";
    hostnames[2][1] = "ccccc";
    hostnames[3][0] = "149.205.36.46";
    hostnames[3][1] = "dddddd";
    hostnames[4][0] = "169.205.36.33";
    hostnames[4][1] = "eeeeee";
    for(int i = 0; i<5; i++) {
        if(!strcmp(hostnames[i][0], client_ip))
            return (char*)hostnames[i][1];
    }
    return NULL;
}

Beginner in C. C 初学者。

I am not sure if there would be a better way to implement what I am trying to implement.我不确定是否有更好的方法来实现我想要实现的内容。 The code is self-explanatory.该代码是不言自明的。 Is there any way that I can predefine the size of hostname, using some general size of IP addresses, to avoid seg fault?有什么方法可以使用 IP 地址的一般大小来预定义主机名的大小,以避免段错误? Is there a even better way where I don't have to hardcode the size?有没有更好的方法让我不必对大小进行硬编码?

After fixing the compiler errors and warnings you get:修复编译器错误和警告后,您会得到:

const char* getClientHostName(const char* client_ip) {

    const char * hostnames[5][2];
    hostnames[0][0] = "122.205.26.34";
    hostnames[0][1] = "aaaaa";
    hostnames[1][0] = "120.205.36.30";
    hostnames[1][1] = "bbbbb";
    hostnames[2][0] = "120.205.16.36";
    hostnames[2][1] = "ccccc";
    hostnames[3][0] = "149.205.36.46";
    hostnames[3][1] = "dddddd";
    hostnames[4][0] = "169.205.36.33";
    hostnames[4][1] = "eeeeee";
    for(int i = 0; i<5; i++) {
        if(!strcmp(hostnames[i][0], client_ip))
            return hostnames[i][1];
    }
    return NULL;
}

int main(int argc, char* argv[]) {
    const char * hostname = getClientHostName("128.205.36.34");
    printf("%s\n", hostname);
}

Is there a even better way where I don't have to hardcode the size?有没有更好的方法让我不必对大小进行硬编码?

Take the habit to compile with all warnings and debug info: gcc -Wall -Wextra -g with GCC .养成编译所有警告和调试信息的习惯: gcc -Wall -Wextra -g with GCC Improve the code to get no warnings at all.改进代码以完全不收到警告。

If you want to get genuine IP addresses, this is operating system specific (since standard C11 don't know about IP addresses; check by reading n1570 ).如果您想获得真正的 IP 地址,这是特定于操作系统的(因为标准C11不知道 IP 地址;请阅读n1570 进行检查)。 On Linux you would use name service routines such as getaddrinfo(3) & getnameinfo(3 ) or the obsolete gethostbyname(3) .在 Linux 上,您将使用名称服务例程,例如getaddrinfo(3) & getnameinfo(3 ) 或过时的gethostbyname(3)

If this is just an exercise without actual relationship to TCP/IP sockets (see tcp(7) , ip(7) , socket(7) ) you could store the table in some global array:如果这只是一个与 TCP/IP 套接字没有实际关系的练习(参见tcp(7)ip(7)socket(7) ),您可以将表存储在某个全局数组中:

 struct myipentry_st {
   const char* myip_hostname;
   const char* myip_address;
 };

then define a global array containing them, with the convention of terminating it by some {NULL, NULL} entry:然后定义一个包含它们的全局数组,约定通过一些{NULL, NULL}条目终止它:

const struct myipentry_st mytable[] = {
    {"aaaaa", "122.205.26.34"},
    {"bbbb", "120.205.36.30"},
    /// etc
    {NULL, NULL} // end marker
};

You'll better have a global or static variable (not an automatic one sitting on the call stack ) because you don't want to fill it on every call to your getClientHostName .您最好有一个全局变量静态变量(而不是位于调用堆栈上的自动变量),因为您不想在每次调用getClientHostName都填充它。

Then your lookup routine (inefficient, since in linear time) would be:那么你的查找例程(效率低下,因为在线性时间内)将是:

const char* getClientHostName(char* client_ip) {
   for (const struct myipentry_st* ent = mytable;
        ent->myip_hostname != NULL;
        ent++)
   // the if below is the only statement of the body of `for` loop
     if (!strcmp(ent->myip_address, client_ip))
         return ent->myip_hostname;
   // this happens after the `for` when nothing was found
   return NULL;
}

You could even declare that table as a heap allocated pointer:您甚至可以将该表声明为堆分配指针:

const struct myipentry_st**mytable;

then use calloc to allocate it and read its data from some text file.然后使用calloc分配它并从某个文本文件中读取它的数据。

Read the documentation of every standard or external function that you are using.阅读您使用的每个标准或外部函数的文档。 Don't forget to check against failure (eg of calloc , like here ).不要忘记检查失败(例如calloc ,就像这里)。 Avoid memory leaks by appropriate calls to free .通过适当调用free来避免内存泄漏 Use the debugger gdb and valgrind .使用调试器gdbvalgrind Beware of undefined behavior .当心未定义的行为

In the real world, you would have perhaps thousands of entries and you would perform the lookup many times (perhaps millions of times, eg once per every HTTP request in a web server or client).在现实世界中,您可能有数千个条目,并且您将执行多次查找(可能数百万次,例如每个 Web 服务器或客户端中的每个HTTP请求一次)。 Then choose a better data structure ( hash table or red-black tree perhaps).然后选择更好的数据结构(可能是哈希表红黑树)。 Read some Introduction to Algorithms .阅读一些算法简介

Add * to type definition char * hostnames[5][2] .*添加到类型定义char * hostnames[5][2] This must be array of pointers, not simple char s.这必须是指针数组,而不是简单的char s。 Another necessary change is strcpy instead of = in strcpy( hostname, getClientHostName("122.205.26.34") );另一个必要的变化是strcpy代替=strcpy( hostname, getClientHostName("122.205.26.34") ); . .

PS: Always try to compile with 0 compiler warnings, not only 0 errors! PS:总是尝试用0个编译器警告进行编译,而不仅仅是0个错误!

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

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