首页 > 解决方案 > 是否有可能通过访问旧的常规 c 中已分配但未初始化的数据来获得分段错误?我看不出怎么

问题描述

我认为应该是一个直截了当的问题,但以防万一上下文有帮助,我将在下面添加一些信息:

我正在为其他人开发一个模块,该模块因 pthread_mutex_unlock(lock); 期间发生的分段错误而崩溃;称呼。我根本没有在我的代码中实现 pthreads,并且调用函数理论上不可能用我所看到的创建分段错误:

bool IsValidTeam(Team4v4Data* td)//pthread_mutex_unlock(mutex* lock) segfaulted here on the log
{
    if (!td)
        return false;
    else if (strncmp (td->captain, "INVALID_CAPTAIN", NAMESIZE) == 0)
        return false;

    //we checked for a null pointer and for the struct w/name  that should be passed during an error,
    //"INVALID_CAPTAIN", as the name, could get a non-null bad pointer but calling function 
    //should handle that in 100% of cases

    //if we did receive bad data though, we never got to the end of this function to the caller
    return true;
}

但是,调用函数不应返回 IsValidTeam 调用的有效数据以外的任何内容:

Team4v4Data* GetCaptainsTeam(Player* p)
{
    MyArenaData* mad = P_ARENA_DATA(arena4v4, arenaKey); //not mine and always works
    
    FOR_EACH_TEAM(t)//#defined as: for (int t = 0; t < MAXTEAMS; t++)
    {
        if (strncmp(mad->team[t].captain, p->name, NAMESIZE) == 0)
        {
            return &mad->team[t];
        }
    }
    //if we got here, none of the teams matched the players name
    //possible returns: a valid team object that matches the players name,
    //or this invalid team object containing td->captain is "INVALID_CAPTAIN"        
    return &mad->INVALID_TEAM;
}

和来电者的来电者:

void Cready(Player* p, params* par, Target* targ, Arena* arena)//unsure of parameters, should be right
{
    Team4v4Data* td = GetCaptainsTeam(p);
    if (!IsValidTeam(td))//segmentation fault here
    {
        td->ready = true;
    }
    //else
        //notify players an error occurred and re-initialize/return the module 
        //to prevent further ones
    
    //do some processing, never got here
}

结构的粗略轮廓:

typedef struct MyArenaData
{
    Team4v4Data team[MAXTEAMS];
    Team4v4Data INVALID_TEAM;//used for error checking in function returns instead of null pointer
//other random bools and data
} MyArenaData;

typedef struct Team4v4Data
{
    char captain[20];//normally initialized to "", but failed to initialize due to bug
    Player4v4Data slots[MAXPLAYERS];//has its own initializers, not used during our error though

//other random bools and data
} Team4v4Data;

typedef struct Player4v4Data
{
    char name[20];//normally initialized to "", but failed to initialize due to bug
    //other player stats
}

因此,当错误发生时,我们发现团队和竞技场数据的位置数据由于标记错误的函数而未初始化。但是,我认为被访问的数据不可能导致分段错误,因为即使没有初始化,它仍然应该是该数据的“正确”内存位置- 任何读取或写入操作都可能导致“意外行为",但程序不应该越过它的缓冲区或读/写随机内存位置,因为指针应该总是指向一个有效的数据区域,按照设计。

我的问题是:我的这种想法是否正确?这个段错误是否可能源于我的代码,还是模块处理程序中的“必须是其他东西”,因为在这种情况下,安全机制无法访问外部内存?

此外,欢迎任何关于空指针安全或更好的数据检查想法的建议。感谢您的关注。

编辑:崩溃日志:

Program received signal SIGSEGV, Segmentation fault.
__pthread_mutex_unlock_usercnt (mutex=0xffffffff, decr=1) at pthread_mutex_unlock.c:41 41      pthread_mutex_unlock.c: No such file
or directory. (gdb) bt
#0  __pthread_mutex_unlock_usercnt (mutex=0xffffffff, decr=1) at pthread_mutex_unlock.c:41
#1  0xf3a0465a in Cready (command=0xffffce3c "ready", params=0x82b3aa8 "\003", p=0xffffd084, target=0x0) at 4v4mod/4v4mod.c:327
#2  0x0807b5bf in run_commands (text=0x8380adf "", p=0x82b3aa8, target=0xffffd084, sound=0) at core/chat.c:366
#3  0x0807b9fd in handle_pub (p=0x82b3aa8, msg=0x8380ad9 "?ready", ismacro=0, isallcmd=0, sound=0) at core/chat.c:448
#4  0x0807c5c9 in PChat (p=0x82b3aa8, pkt=0x8380ad4 "\006\002", len=12) at core/chat.c:667

(gdb) frame 1
#1  0xf3a0465a in Cready (command=0xffffce3c "ready", params=0x82b3aa8 "\003", p=0xffffd084, target=0x0) at 4v4mod/4v4mod.c:327 327          
if (!IsValidTeam(td)) //player was not a captain, do nothing (gdb)
info locals td = 0xffffffff mad = 0xdfd7c300 (gdb) info args command =
0xffffce3c "ready" params = 0x82b3aa8 "\003" p = 0xffffd084 target =
0x0

标签: cpointersstructsegmentation-faultpthreads

解决方案


推荐阅读