zoukankan      html  css  js  c++  java
  • 使用opencv传中文文件崩溃

    这个问题经过我的调试发现:
      程序是在
    while (*at && !isdigit(*at)) at++;  
    这个语句时crash的,但是跟进去是isdigit的问题,因为变量at的声明是char* at;  当at指向一个中文路径的时候,在传递给 isdigit时,*at类型很明显,隐式转换成为了int,因为  isdigit(int c)是这样声明的。所以这个时候一下子int c变成了一个负数:0xffffffb2,然后再往下跟进执行到 _ASSERTE((unsigned)(c + 1) <= 256);这个语句才崩溃的,因为强制转换成无符号的int,变成了一个很大的正数。明显不满足断言条件,所以程序当然crash了。
     
    以上的crash情况只有在Debug版本才会crash,Release版本就不会出问题。原因已经在微软带的CRT库的源码中看出来了
     
    结论:
       应该是我们使用的问题,中文windows默认的locale是GB2312的,我们很可能却调用ASCII版本的 isdigit函数(所以遇到中文立即crash),这已经不符合逻辑了,咱不可能手动去改变locale。
     
    下面是opencv源码中造成崩溃的函数源码(注意第三十行造成crash的语句):
     1 static char* icvExtractPattern(const char *filename, unsigned *offset)
     2 {
     3     char *name = (char *)filename;
     4 
     5     if( !filename )
     6         return 0;
     7 
     8     // check whether this is a valid image sequence filename
     9     char *at = strchr(name, '%');
    10     if(at)
    11     {
    12         int dummy;
    13         if(sscanf(at + 1, "%ud", &dummy) != 1)
    14             return 0;
    15         name = strdup(filename);
    16     }
    17     else // no pattern filename was given - extract the pattern
    18     {
    19         at = name;
    20 
    21         // ignore directory names
    22         char *slash = strrchr(at, '/');
    23         if (slash) at = slash + 1;
    24 
    25 #ifdef _WIN32
    26         slash = strrchr(at, '\');
    27         if (slash) at = slash + 1;
    28 #endif
    29 
    30         while (*at && !isdigit(*at)) at++;
    31 
    32         if(!*at)
    33             return 0;
    34 
    35         sscanf(at, "%u", offset);
    36 
    37         int size = (int)strlen(filename) + 20;
    38         name = (char *)malloc(size);
    39         strncpy(name, filename, at - filename);
    40         name[at - filename] = 0;
    41 
    42         strcat(name, "%0");
    43 
    44         int i;
    45         char *extension;
    46         for(i = 0, extension = at; isdigit(at[i]); i++, extension++)
    47             ;
    48         char places[10];
    49         sprintf(places, "%dd", i);
    50 
    51         strcat(name, places);
    52         strcat(name, extension);
    53     }
    54 
    55     return name;
    56 }

    下面是个最小的崩溃场景例子:

     1 #include<ctype.h>
     2 #include<stdio.h>
     3 
     4 
     5 int main(){
     6 
     7     char *pPath = "测试视频";
     8     #if defined (_DEBUG)
     9     if(!isdigit(*pPath)){
    10         printf("its not digit
    ");
    11     }
    12   #else
    13     if(!iswdigit(*pPath)){
    14         printf("Release its not digit
    ");
    15     }
    16   #endif
    17     return 0;
    18 }

    以下是一个测试:

     1 #include <stdio.h>
     2 #include <Windows.h>
     3 
     4 int NarrowChar() {
     5     char *pcAlpha = "";
     6     printf("pcAlpha  = 0x%08X!
    ", *pcAlpha); //0xFFFFFFB0
     7     return 0;
     8 }
     9 
    10 int WideChar() {
    11     //wchar_t *pwcAlpha = L"A";
    12     wchar_t *pwcAlpha = L"";
    13     printf("pwcAlpha  = 0x%08X!
    ", *pwcAlpha); //0x0000554A    UTF-16-little-endian
    14     //wprintf(L"pwcAlpha  = 0x%08X!
    ", *pwcAlpha); //0x0000554A
    15     return 0;
    16 }
    17 
    18 int main(void) {
    19      NarrowChar();
    20      WideChar();
    21 
    22      return 0;
    23 }

    由以上可以看出来,字符串这个前缀‘L’实质上是对字符串从ANSI字符集转换为Unicode字符集,也就是UTF-16编码。如果不加这个L前缀就是ANSI/ASCII字符集。

    以上的问题我前博文已经研究过了。

    ################################update#############################

    结论:

    经过调试测试,其实就是cvCreateFileCapture函数返回失败的原因,在opencv 2.4.9和opencv2.4.10中就有问题,就是都返回失败,而2.4.6就不会

    references:

    http://www.cppblog.com/luonjtu/archive/2009/03/13/76332.html

    http://comments.gmane.org/gmane.comp.lib.opencv.devel/1274

    http://msdn.microsoft.com/en-us/library/windows/desktop/ff381407(v=vs.85).aspx

    http://blog.csdn.net/xiaobai1593/article/details/7063535

    http://stackoverflow.com/questions/8032080/how-to-convert-char-to-wchar-t

     
  • 相关阅读:
    前后端交互, 安装drf, restful接口规范, pycharm断点调试
    django中文设置, axios, CORS, 全局js配置, Vue配置jq + bs
    js原型, Vue项目环境搭建, Vue项目目录结构, Vue项目生命周期, 小组件使用, 全局样式, 路由跳转, 组件的生命周期钩子, 路由传参
    Vue组件
    Vue表单指令, 条件指令, 循环指令, 成员
    question1 赋值运算操作符
    CH15 面向对象程序设计
    CH12 动态内存
    CH11 关联容器
    CH10 泛型算法
  • 原文地址:https://www.cnblogs.com/foohack/p/4171215.html
Copyright © 2011-2022 走看看