0

我正在尝试在可以与套接字连接的服务器上创建一个简单的管理器客户端 CRUD(用 C 语言,一种我不太熟悉但我别无选择的语言)。通过使用会话 ID,服务器将同时保持 10 个同时连接。问题是,当我在添加 10 个客户端后打印列表时,它会显示一个包含 10 次相同对象的列表(或 10 个具有相同 ID 的对象,这让我有点困惑)。

这就是我声明经理客户端的结构并声明列表(可以容纳其中的 10 个)的方式:

typedef struct Mana_client {
    int client_id;
    int timestamp_connection;
    char privilege_level;
}Mana_client;

Mana_client *mana_client_list[10];
srand(time(NULL)); // is called once when initializing the thread.

这就是我写“将客户添加到列表”的方式:

int add_mana_client()
{
    int i=0;
    int client_id = 0;
    int timestamp = 0;
    Mana_client client = { client_id, timestamp, 1};
    client_id = rand()%100000;
    timestamp = time(NULL);
    client.client_id =  &client_id;
    client.timestamp_connection = &timestamp;
    for(i=0; i <10; i++)
    {
        if(mana_client_list[i] == NULL){
            printf("%u. Empty spot in list\n", i);
            if(!contains_mana_client_id(client_id)){
                printf("%u. Adding client... (with ID%u)\n", i, client.client_id);
                mana_client_list[i] = &client;
                return client_id;
            }
        }
    }
    return 0;
}

这就是我检查具有相同 ID 的客户端是否已在列表中的方式:

int contains_mana_client_id(int id)
{
    int i=0;
    for(i=0; i <10; i++)
    {
        if(mana_client_list[i] != NULL){
            if(id == mana_client_list[i]->client_id){
                printf("%u. Client with ID=%u found.\n", i, id);
                return 1;
            }
        }
    }
    return 0;
}

然后,检查列表及其客户:

void print_mana_client_list()
{
    int i=0;
    printf("Printing list of mana clients...\n\n");
    for(i=0; i <10; i++)
    {
        if(mana_client_list[i] != NULL){
            printf("%u. Client with ID=%u.\n", i, mana_client_list[i]->client_id);
        }else{
            printf("%u. Empty.\n", i);
        }
    }
}

在运行该方法以连续 12 次添加客户端并打印列表后,我得到以下输出:

  1. 列表中的空白点
  2. 添加客户端...(ID94630956) 添加了管理客户端(ID=41)。
  3. 列表中的空白点
  4. 添加客户端...(ID94630956)已添加管理客户端(ID=18467)。
  5. 列表中的空白点
  6. 添加客户端...(使用 ID94630956)添加了管理客户端(使用 ID=6334)。
  7. 列表中的空白点
  8. 添加客户端...(ID94630956)添加了管理客户端(ID=26500)。
  9. 列表中的空白点
  10. 添加客户端...(ID94630956)已添加管理客户端(ID=19169)。
  11. 列表中的空白点
  12. 添加客户端...(使用 ID94630956)添加了管理客户端(使用 ID=15724)。
  13. 列表中的空白点
  14. 添加客户端...(ID94630956)添加了管理客户端(ID=11478)。
  15. 列表中的空白点
  16. 添加客户端...(使用 ID94630956)添加了管理客户端(使用 ID=29358)。
  17. 列表中的空白点
  18. 添加客户端...(使用 ID94630956)添加了管理客户端(使用 ID=26962)。
  19. 列表中的空白点
  20. 添加客户端...(使用 ID94630956)添加了管理客户端(使用 ID=24464)。

添加了管理客户端(ID=0)。

添加了管理客户端(ID=0)。

打印 mana 客户列表...

  1. ID = 3435973836 的客户端。
  2. ID = 3435973836 的客户端。
  3. ID = 3435973836 的客户端。
  4. ID = 3435973836 的客户端。
  5. ID = 3435973836 的客户端。
  6. ID = 3435973836 的客户端。
  7. ID = 3435973836 的客户端。
  8. ID = 3435973836 的客户端。
  9. ID = 3435973836 的客户端。
  10. ID = 3435973836 的客户端。

我个人认为问题与我存储或传递对象/值的方式有关,但我并不完全确定。对此的任何帮助将不胜感激。

4

1 回答 1

1

这是因为它们相同的。当你这样做

mana_client_list[i] = &client;

您一直使用指向局部变量的指针。相反,您应该为循环中的每次迭代创建一个新的结构实例。为此,您需要使用malloc为结构分配内存。完成后不要忘记free那段记忆。

add_mana_client这也将解决您遇到的另一个问题,那就是您保存指向局部变量的指针,一旦函数返回,它将超出范围。在函数返回后使用该指针是未定义行为的一种情况,你很幸运它可以工作。


一种简单的方法,无需对当前代码进行许多修改,可能类似于以下代码来替换当前mana_client_list[i] = &client;行:

mana_client_list[i] = malloc(sizeof(Mana_client));
*mana_client_list[i] = client;

这会分配一个新结构,并将已经初始化的结构复制到该新结构。

于 2013-11-05T12:12:14.547 回答