首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用struct的Seg错误

使用struct的Seg错误
EN

Stack Overflow用户
提问于 2012-11-26 16:44:50
回答 3查看 120关注 0票数 1

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

代码语言:javascript
复制
/** 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./ User键入程序名称和标志选项,例如:program -test a -test2 b

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

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

程序会编译,但我对指针和引用还是新手(我认为&被称为引用),所以也许这就是程序出错的原因。

任何帮助都是非常感谢的!此外,如果您发现任何问题或更好的方法来处理assemble_url,也请让我知道(我认为它不是以最好的方式处理的,但就像我说的,我对C编程非常陌生)

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2012-11-26 16:51:39

此初始化

代码语言:javascript
复制
int opt_len = sizeof(&cmd->options);

会给出一个指针&cmd->options的字节大小。这在您试图做的事情的上下文中是没有意义的。

如果想要确定数组中元素的数量(假设它还没有衰减到指针),正确的方法应该是

代码语言:javascript
复制
int opt_len = sizeof cmd->options / sizeof *cmd->options;

在这种情况下,opt_len将使用MAX_OPTIONS值进行初始化(这意味着您可以使用MAX_OPTIONS来代替它)。

票数 1
EN

Stack Overflow用户

发布于 2012-11-26 16:53:35

你有大量的内存从连接字符串泄漏。每次调用都会分配一个新的缓冲区,但是你从来没有去释放它们,而且你释放了指针,所以再也没有机会释放那个内存了。

这不是segfault的原因。

票数 1
EN

Stack Overflow用户

发布于 2013-04-08 22:22:05

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

代码语言:javascript
复制
#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;
 }

您可以这样使用它:

代码语言:javascript
复制
char* x = stringBuilder(4,"hello", " ", "world", "\n");
printf(x);
free(x);

还要注意,为了应用程序的目的,键和值都必须是URL编码的

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13561304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档