1

私は約 1 週間 C を書いていますので、ご容赦ください。メソッドでセグメンテーション違反エラーが発生しましたが、その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) とそれに関連付けられた値 (value) があります。

3./ 次に、プログラムは、次のようなオプション キーと値を使用して URL を作成しようとします。http://url/?test=a&test2=b

プログラムはコンパイルされますが、私はまだポインターと参照に慣れていないため (& は参照と呼ばれていると思います)、おそらくそれがプログラム エラーの原因です。

どんな助けでも大歓迎です!また、問題や assemble_url を処理するためのより良い方法を見つけた場合は、私にも知らせてください (最善の方法で処理されているとは思いませんが、私が言ったように、私は C プログラミングに非常に慣れていません)。

ありがとう!

4

3 に答える 3

1

この初期化

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

ポインタのバイトサイズが表示されます&cmd->options。これは、あなたがやろうとしていることの文脈では意味がありません。

配列内の要素の数を決定する場合(ポインターに減衰していないと仮定)、適切な手法は次のようになります。

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

この場合、値opt_lenで初期化されMAX_OPTIONSます(つまりMAX_OPTIONS、代わりに使用できます)。

于 2012-11-26T08:51:39.053 に答える
1

concatstringから大量のメモリリークが発生しています。呼び出しごとに新しいバッファが割り当てられますが、わざわざそれらを解放することはなく、ポインタを失うため、そのメモリを再び解放する可能性はありません。

これはセグメンテーション違反の原因ではありません。

于 2012-11-26T08:53:35.367 に答える
1

3 つ以上の文字列を連結しているため、一度にすべての連結にメモリを割り当てた方がよいでしょう。

#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 エンコードする必要があることに注意してください。

于 2013-04-08T14:22:04.647 に答える