| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1358 人关注过本帖
标题:free时偶尔出现堆不存在的bug
只看楼主 加入收藏
knightfyx
Rank: 1
等 级:新手上路
帖 子:8
专家分:5
注 册:2018-3-7
结帖率:100%
收藏
 问题点数:0 回复次数:3 
free时偶尔出现堆不存在的bug
是这样,小弟最近用递归写了一个穷举汉明距离为n以内的全部字符串(字符只有ATCG四种)的函数,这个函数本身已经跑通了,输出也没问题,但是在释放申请的内存空间时偶尔会出现堆不存在的bug,不知是否有大佬愿意帮我看一眼,bug出现在111行的位置
程序代码:
//建立群,输入一个字符串和一个距离值,输出字符串数组
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<math.h>
//记得返回值是新的tail_count
//三种情况:正常序列、只剩一个字符、没有错误匹配
char**nbor_l(char*seq, int mis, int*amount)//依次是:序列、距离、总量的指针(为了返回总量),需要输出两个值,序列空间和序列总量,别忘了!!
{
    if(mis==0)//没有错误匹配:返回原序列
    {
        char **ss = (char**)malloc(4);
        *amount = 1;
        *ss = seq;
        return ss;
        //一旦传过来的seq被free掉,ss就会变成野指针,不能再调用了一定要注意啊
    }
    int len = strlen(seq);//字符串的长度
    int loop_a = 0, loop_b = 0;
    char s_c = '\0';
    if (len == 1)//只剩一个字符:返回ATCG的二维数组
    {
        char**ss = (char**)malloc(20), **ss_ing = ss;//定义时候多留一个指针的空间以防止ss_ing变成野指针
        char*s = NULL;
        for (loop_a = 0; loop_a < 4; loop_a++)
        {
            s = (char*)malloc(2);
            *(s + 1) = '\0';
            switch(loop_a)
            {
            case 0:s_c = 'A'; break;
            case 1:s_c = 'T'; break;
            case 2:s_c = 'C'; break;
            case 3:s_c = 'G'; break;
            }
            *s = s_c;
            *ss_ing = s;
            ss_ing++;
        }
        *amount = 4;
        return ss;
    }
    else//正常序列:三步走1.分两种情况把末尾去掉调用自己2.根据字符是否相同叠合3.free上级指针,返回自己的空间
    {
        char*seq_n = (char*)malloc(len);
        strncpy(seq_n, seq, len - 1);
        *(seq_n + len - 1) = '\0';
        int count_0 = 0, count_1 = 0;
        char**ss_0 = nbor_l(seq_n, mis, &count_0);//0表示相同
        char**ss_1 = nbor_l(seq_n, mis - 1, &count_1);//1表示不同,这两个是第一步,调用自己
        int mark = 0, count = 0;
        char**ss_n = (char**)malloc(4 * (3 * count_1 + count_0 + 1));
        char**ss_ing = NULL, **ss_ing_n =ss_n;//这两个记得初始化
        char*_tmp = NULL;
        for (loop_a = 0; loop_a < 4; loop_a++)
        {
            switch (loop_a)
            {
            case 0:s_c = 'A'; break;
            case 1:s_c = 'T'; break;
            case 2:s_c = 'C'; break;
            case 3:s_c = 'G'; break;
            }
            mark = (s_c == *(seq + len - 1)) ? 0 : 1;
            if (mark)
            {
                ss_ing = ss_1;
                for (loop_b = 0; loop_b < count_1; loop_b++)
                {
                    _tmp = (char*)malloc(len + 2);
                    strcpy(_tmp, *ss_ing);
                    *(_tmp + len-1) = s_c;
                    *(_tmp + len) = '\0';
                    *ss_ing_n = _tmp;
                    ss_ing_n++;
                    ss_ing++;
                    count++;
                }
            }
            else 
            {
                ss_ing = ss_0;
                for (loop_b = 0; loop_b < count_0; loop_b++)
                {
                    _tmp = (char*)malloc(len + 2);
                    strcpy(_tmp, *ss_ing);
                    *(_tmp + len-1) = s_c;
                    *(_tmp + len) = '\0';
                    *ss_ing_n = _tmp;
                    ss_ing_n++;
                    ss_ing++;
                    count++;
                }

            }

        }
        *amount = count;
        //free掉上个函数返回的东西防止资源浪费
        ss_ing = ss_0;
        /*check1//
        printf("newly dropped as belows\n");
        //check1*/
        for (loop_a = 0; loop_a < count_0; loop_a++)
        {
            /*check2//
            printf("%s\n", *ss_ing);
            //check2*/
            free((void*)(*ss_ing));
            ss_ing++;
        }
        free((void*)ss_0);
        ss_ing = ss_1;
        for (loop_a = 0; loop_a < count_1; loop_a++)
        {
            free((void*)(*ss_ing));
            ss_ing++;
        }
        free((void*)ss_1);
        /*check3//
        ss_ing = ss_n;
        printf("these sequences are\n");
        for (loop_a = 0; loop_a < count; loop_a++)
        {
                
            printf("%s\n", *ss_ing);
            ss_ing++;
                
        }
        //check3*/
        return ss_n;
    }
}

给大佬提前说声感谢了,此外,由于本人并非科班出身,代码的可读性、规范性和效率都比较差,因此想找个师父帮忙规范规范,有什么小任务小算法程序交给我也是完全OK的。
搜索更多相关主题的帖子: for free break case char 
2021-06-01 10:47
自由而无用
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:61
专家分:1456
注 册:2021-8-9
收藏
得分:0 
for (loop_a = 0; loop_a < count_0; loop_a++)
free((void*)(*ss_ing));
char**ss_0 = nbor_l(seq_n, mis, &count_0)

check mis value outside function nbor_l
2021-08-13 09:12
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9029
专家分:54050
注 册:2011-1-18
收藏
得分:0 
不要乱分配内存,不要瞎递归

程序代码:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

static bool __hamming_next_character( char* pc, char ignore )
{
    if( *pc == ignore )
        *pc = 0;

    if( *pc<'A' && ignore!='A' )
        *pc = 'A';
    else if( *pc<'C' && ignore!='C' )
        *pc = 'C';
    else if( *pc<'G' && ignore!='G' )
        *pc = 'G';
    else if( *pc<'T' && ignore!='T' )
        *pc = 'T';
    else
        *pc = ignore;

    return *pc!=ignore;
}

bool hamming_next( size_t mis, const char* src, char* dst )
{
    size_t miscount = 0;
    for( size_t i=0; src[i]; ++i )
        miscount += src[i]!=dst[i];

    if( miscount < mis )
    {
        if( src[0] && dst[0]==src[0] && __hamming_next_character(&dst[0],src[0]) )
            return true;
    }

    for( size_t i=0; src[i]; ++i )
    {
        if( dst[i] != src[i] )
        {
            if( __hamming_next_character(&dst[i],src[i]) )
                return true;

            if( src[i+1] && dst[i+1]==src[i+1] )
            {
                __hamming_next_character( &dst[i+1], src[i+1] );
                return true;
            }
        }
    }

    return false;
}

int main( void )
{
    const char* src = "CCC";
    const size_t mis = 2;

    size_t count = 0;
    char dst[1000];
    strcpy( dst, src );
    for( bool b=true; b; b=hamming_next(mis,src,dst),++count )
    {
        puts( dst );
    }
    printf( "如上,汉明距离不大于 %zu 的字符串一共有 %zu 个。\n", mis, count );
}


输出
CCC
ACC
GCC
TCC
CAC
AAC
GAC
TAC
CGC
AGC
GGC
TGC
CTC
ATC
GTC
TTC
CCA
ACA
GCA
TCA
CAA
CGA
CTA
CCG
ACG
GCG
TCG
CAG
CGG
CTG
CCT
ACT
GCT
TCT
CAT
CGT
CTT
如上,汉明距离不大于 2 的字符串一共有 37 个。
2021-08-13 15:06
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9029
专家分:54050
注 册:2011-1-18
收藏
得分:0 
另外,数量可以通过公式直接算出来

程序代码:
#include <stdio.h>
#include <assert.h>

// 参数分别是 字符串长度、允许的汉明距离
size_t foo( size_t str_len, size_t mis )
{
    if( mis > str_len )
        mis = str_len;

    size_t a=1, b=1;
    size_t result = a*b;
    for( size_t i=0; i!=mis; ++i )
    {
        assert( a * (str_len-i) / (str_len-i) == a ); // 检测溢出
        a = a * (str_len-i) / (i+1);

        assert( b * 3 / 3 == b ); // 检测溢出
        b *= 3;

        assert( result + a*b > result ); // 检测溢出
        result += a*b;
    }
    return result;
}

int main( void )
{
    printf( "%u\n", foo(3,0) ); // 正确结果应当输出 1
    printf( "%u\n", foo(3,1) ); // 正确结果应当输出 10
    printf( "%u\n", foo(3,2) ); // 正确结果应当输出 37
    printf( "%u\n", foo(3,3) ); // 正确结果应当输出 64
    printf( "%u\n", foo(3,4) ); // 正确结果应当输出 64
    printf( "%u\n", foo(10,7) ); // 正确结果应当输出 497452
}
2021-08-13 16:58
zhaoya881010
Rank: 9Rank: 9Rank: 9
来 自:芒砀古郡
等 级:蜘蛛侠
威 望:1
帖 子:339
专家分:1177
注 册:2010-11-21
收藏
得分:0 
还是每天这么活跃。

Go Go Go
2021-08-13 18:11
快速回复:free时偶尔出现堆不存在的bug
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.032102 second(s), 11 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved