使用struct进行段错误

时间:2012-11-26 08:44:50

标签: c concat

我已经写了大约一个星期了,所以请耐心等待。我在方法assemble_url中遇到了分段错误错误,我不知道为什么。这是我的代码:

/** 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;
}

此计划的内容如下:

1. /用户输入程序名称和标志选项,如下所示:  program -test a -test2 b

2. /程序解析命令并使用选项填充命令结构。每个选项都有一个标志(argname)和与之关联的值(值)

3. /程序然后尝试使用这些选项键和值创建URL,例如http://url/?test=a&test2=b

程序编译,但我仍然是指针和引用的新手(我认为&amp;被称为参考),所以也许这就是程序错误的原因。

非常感谢任何帮助!另外,如果你看到任何探测器或更好的方法来处理assemble_url,也请让我知道(我不认为它以最好的方式处理,但就像我说的,我是C编程的新手)

谢谢!

3 个答案:

答案 0 :(得分:1)

此初始化

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

将为您提供指针&cmd->options的字节大小。在你想要做的事情的背景下,这没有任何意义。

如果你想确定数组中元素的数量(假设它没有衰减到指针),那么正确的技术将是

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

在这种情况下,opt_len将使用MAX_OPTIONS值进行初始化(这意味着您可以在其位置使用MAX_OPTIONS。)

答案 1 :(得分:1)

你有来自concatstring的大量内存泄漏。每次调用都会分配一个新的缓冲区,但你永远不会费心去释放它们,并且你松开了指针,所以没有机会再次释放那个内存。

这不是段错误的原因。

答案 2 :(得分:1)

因为你连接了两个以上的字符串,所以最好一次为所有连接分配内存。

#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;
 }

你可以这样使用它:

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

另请注意,出于应用程序的目的,键和值都必须是URL编码的