简体   繁体   English

使用struct进行段错误

[英]Seg fault using struct

I have been writing C for approximately a week, so bear with me. 我已经写了大约一个星期了,所以请耐心等待。 I'm getting a segmentation fault error in the method assemble_url and I dont know why. 我在方法assemble_url遇到了分段错误错误,我不知道为什么。 Here is my code: 这是我的代码:

/** Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

/** Definitions */
#define MAX_OPTIONS 32
#define MAX_ARGS 32

/** Command option */
typedef struct {
    char *argname;
    char *value;
} command_option;

/** Command */
typedef struct {
    command_option options[MAX_OPTIONS];
} command_t;

/**
 * Prints the arguments passed in in a hashmap format (key => value)
 */
void populate_command(command_t *cmd,int argc,char *argv[])
{
    int i,j=0;

    /** Check to see if we have arguments. If argc is equal to 1 than there are no arguments besides the filename */
    if(argc>1)
    {

        /* Start at position 1, since argv[0] is the filename being called */
        for(i=1;i<argc;i++)
        {

            /* Head of argv array */
            char *arg = argv[i];

            /* Create a copy of head for traversal. */
            char *c = arg;

            /* traverse the char array, ensuring we arent dealing with NULL values(c!==NULL) and NULL pointers(*c!=='\0') */
            while(*c != '\0' && c != NULL)
            {

                /* Were only concerned with parsing the flags and obtaining the flag value. */
                if(strchr("-",*c))
                {

                    char *key = c; /* Key */
                    char *value = argv[i+1]; /* Value */

                    /* ensure we have a value existent for key */
                    if(strchr("-",*value))
                    {
                        /** user supplied a key with no value */
                        break;
                    }
                    command_option *option = &cmd->options[j];
                    option->argname = key;
                    option->value   = value;

                    j++;

                    /* Debug dump */
                    printf("arg %d: %s -> %s\n",i,option->argname,option->value);

                }/* end strchr */

                /** Increment the traversal array */
                c++;

            }/* end while loop */

        }/* end forloop */

    }/* endif */

}/** end print_args */

/**
 * Concatenates two strings and returns the resulting concatenated string
 */
char* concatstring(char *s1,char *s2)
{
    /* Allocate memory for *result. We add 1 to account for the extra byte to store the null character. Strlen accounts for all
     non-null bytes, so using strlen(s1) + strlen(s2) + 1 ensures that an overflow wont occur. An overflow occurs when
     the number of bytes being used (in our example, is the addition of strlen for s1 and s2) is more than the number of bytes
     allocated (in our example, the number of bytes allocated to *result)*/
    char *result = malloc(strlen(s1)+strlen(s2)+1);

    /*Copies the C string pointed by source(s1) into the array pointed by destination(result), including the terminating null character. */
    strcpy(result,s1);

    /* appends a copy of the source string(s2) to the destination string(result). The terminating null character in
     destination is overwritten by the first character of source, and a null-character is included at
     the end of the new string formed by the concatenation of both in destination.*/
    strcat(result,s2);

    /* return result */
    return result;

} /** end concatstring */

char* assemble_url(command_t *cmd,char *str)
{
    int i,opt_len = sizeof(&cmd->options);
    for(i=0;i<opt_len;i++)
    {
        command_option *option = &cmd->options[i];
        char *key = option->argname;
        char *value = option->value;
        if(i==0)
        {
            str = concatstring(str,key);
            str = concatstring(str,"=");
            str = concatstring(str,value);
        }
        else
        {
            str = concatstring(str,"&");
            str = concatstring(str,key);
            str = concatstring(str,"=");
            str = concatstring(str,value);
        }
    }
    return str;
}

What occurs in this program is the following: 该计划中发生的情况如下:

1./ User types in program name and flag options,such as the following: program -test a -test2 b 1. /用户输入程序名称和标志选项,如下所示: program -test a -test2 b

2./ The program parses the command and populates a command struct with options. 2. /程序解析命令并使用选项填充命令结构。 Each option has a flag(argname) and value associated to it(value) 每个选项都有一个标志(argname)和与之关联的值(值)

3./ The program then tries to create a URL with those option keys and values, such as http://url/?test=a&test2=b 3. /程序然后尝试使用这些选项键和值创建URL,例如http://url/?test=a&test2=b

The program compiles but I'm still new to pointers and references (I think & is called a reference), so maybe that is why the program errors. 程序编译,但我仍然是指针和引用的新手(我认为&称为参考),所以也许这就是程序错误的原因。

Any help is greatly appreciated! 任何帮助是极大的赞赏! Also, if you see any probems or better way to handle assemble_url, please also let me know (I dont think its being handled in the best way, but like I said, I'm extremely new to C programming) 另外,如果你看到任何探测器或更好的方法来处理assemble_url,也请让我知道(我不认为它以最好的方式处理,但就像我说的,我是C编程的新手)

Thanks! 谢谢!

This initialization 这个初始化

int opt_len = sizeof(&cmd->options);

will give you the byte-size of a pointer &cmd->options . 将为您提供指针&cmd->options的字节大小。 This makes no sense in the context of what you are trying to do. 在你想要做的事情的背景下,这没有任何意义。

If you want to determine the number of elements in an array (assuming it hasn't decayed to pointer), the proper technique would be 如果你想确定数组中元素的数量(假设它没有衰减到指针),那么正确的技术就是

int opt_len = sizeof cmd->options / sizeof *cmd->options;

In this case opt_len will be initialized with MAX_OPTIONS value (meaning that you can just use MAX_OPTIONS in its place). 在这种情况下, opt_len将使用MAX_OPTIONS值进行初始化(这意味着您可以在其位置使用MAX_OPTIONS )。

You have massive memory leaks from concatstring. 你有来自concatstring的大量内存泄漏。 Each invocation allocates a new buffer but you never bother to free them, and you loose the pointers so no chance of ever freeing that memory again. 每次调用都会分配一个新的缓冲区,但你永远不会费心去释放它们,并且你松开了指针,所以没有机会再次释放那个内存。

This is not the cause of the segfault. 这不是段错误的原因。

Because you are concatenating more than two strings it would be best if you allocated memory for all concatenations at once. 因为你连接了两个以上的字符串,所以最好一次为所有连接分配内存。

#include <stdarg.h>
#include <string>
char* stringBuilder(int count, ...)
{
    va_list ap, vacnt;
    int j;
    int len = 1;
    char* buffer;
    va_start(ap, count); 
#ifdef va_copy
        va_copy(vacnt,ap);
#else
    vacnt = ap;
#endif
    for(j=0; j<count; ++j){
        len+=strlen(va_arg(vacnt, char*)); 
    }
    va_end(vacnt);
    buffer = (char*) malloc(len * sizeof(char));
    buffer[0]=0;
    for (j=0;j<count;++j) {
       strcat (buffer, va_arg(ap, char*));
    }
    va_end(ap);
    return buffer;
 }

You can use it as such: 您可以这样使用它:

char* x = stringBuilder(4,"hello", " ", "world", "\n");
printf(x);
free(x);

Also note that both key and value must be URL-Encoded for the purposes of your application 另请注意,为了您的应用程序,键和值必须是URL编码

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

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