工具:valgrind学习

2023-10-31

概述

体系结构

Valgrind 是一套linux下,开放源代码的仿真调试工具的集合。Valgrind有内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架,它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件,利用内核提供的服务完成各种特定的内存调试任务。

在这里插入图片描述
Valgrind 包括如下一些工具:

  • Memcheck。这是 valgrind 应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等
  • Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
  • Cachegrind。它主要用来检查程序中缓存使用出现的问题。
  • Helgrind。它主要用来检查多线程程序中出现的竞争问题。
  • Massif。它主要用来检查程序中堆栈使用中出现的问题。
  • Extension。可以利用 core 提供的功能,自己编写特定的内存调试工具。

Valgrind 原理

valgrind是一个提供了一些debug和优化工具的工具箱,可以使得你的程序减少内存泄漏或者错误访问.

valgrind 默认使用 memcheck 去检查内存问题.

memcheck 检测内存问题的原理如下图所示:
在这里插入图片描述
Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。

  • valid-value map:
    对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于 CPU 的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。
  • valid-address map
    对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。

检测原理:

  • 当要读写内存中某个字节时,首先检查 valid-address map 中这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。
  • 内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit (在 valid-value map 中) 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的 V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。

安装

centos下:

sudo yum install valgrind

源代码方式安装:

wget https://fossies.org/linux/misc/valgrind-3.15.0.tar.bz2
tar -jxvf valgrind-3.15.0.tar.bz2
cd valgrind-3.15.0
./configure 
make 
sudo make install

编译时需要注意

1、为了使 valgrind 发现的错误更精确,如能够定位到源代码行,建议在编译时加上-g
参数,编译优化选项请选择 O0,虽然这会降低程序的执行效率。

对于CMakelist

add_definitions("-Wall -g")

2、对于C++程序,请启动-fno-inline忽略代码中的 inline 关键字,该选项使编译器将内联函数以普通函数对待;等同无优化选项时的处理)。这样可以更轻松地查看函数调用链。

或者,Valgrind选项 --read-inline-info=yes指示Valgrind读取描述内联信息的调试信息

快速入门

使用valgrind 很简单, 首先编译好要测试的程序 (为了使valgrind发现的错误更精确,如能够定位到源代码行,建议在编译时加上-g参数,编译优化选项请选择O0,虽然这会降低程序的执行效率。), 假设运行这个程序的命令是

./a.out arg1 arg2

那么要使用 valgrind 的话只需要运行

valgrind --leak-check=yes ./a.out arg1 arg2

LEAK SUMMARY:内存泄漏总结(分类)

definitely lost: 4 bytes in 1 blocks:绝对丢失,这种情况应该由程序员来解决,下面几种情况,可以当作参考

  • indirectly lost: 0 bytes in 0 blocks:间接丢失
  • possibly lost: 0 bytes in 0 blocks:可能丢失
  • still reachable: 0 bytes in 0 blocks:仍然可以访问
  • suppressed: 0 bytes in 0 blocks:抑制错误中的丢失

实践

第一个例子:没有内存泄漏

#include <iostream.h>
int main()
{
 cout << "Hello kiccleaf!/n" << endl;
 return 0;
}

编译

gcc -o ./Share ./main.cpp

运行:

valgrind --tool=memcheck --leak-check=full ./Share

结果:

==56806== Memcheck, a memory error detector
==56806== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==56806== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==56806== Command: ./Share
==56806== 
Hello kiccleaf!/n
==56806== 
==56806== HEAP SUMMARY:
==56806==     in use at exit: 0 bytes in 0 blocks
==56806==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==56806== 
==56806== All heap blocks were freed -- no leaks are possible
==56806== 
==56806== For lists of detected and suppressed errors, rerun with: -s
==56806== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

第二个例子:只申请内存而不释放

#include <stdlib.h>
#include <stdio.h>
void func()
{
 //只申请内存而不释放
    void *p=malloc(sizeof(int));
}
int main()
{
    func();
    getchar();
    return 0;
}

编译程序1

gcc -o ./a.out ./main.cpp

使用valgrind命令来执行程序同时输出日志到文件

valgrind --log-file=valReport --leak-check=full --show-reachable=yes --leak-resolution=low ./a.out
  • –log-file=valReport 是指定生成分析日志文件到当前执行目录中,文件名为valReport
  • –leak-check=full 显示每个泄露的详细信息
  • –show-reachable=yes 是否检测控制范围之外的泄漏,比如全局指针、static指针等,显示所有的内存泄露类型
  • –leak-resolution=low 内存泄漏报告合并等级

最后执行输出的内容如下

报告解读,其中54017是指进程号,如果程序使用了多进程的方式来执行,那么就会显示多个进程的内容

第一段是valgrind的基本信息

==54017== Memcheck, a memory error detector
==54017== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==54017== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==54017== Command: ./a.out
==54017== Parent PID: 52130

第二段是对堆内存分配的总结信息,其中提到程序一共申请了1次内存,其中0次释放了,4 bytes被分配

==54017== HEAP SUMMARY:
==54017==     in use at exit: 4 bytes in 1 blocks
==54017==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated

第三段的内容描述了内存泄露的具体信息,其中有一块内存占用4字节,在调用malloc分配,调用栈中可以看到是func函数最后调用了malloc,所以这一个信息是比较准确的定位了我们泄露的内存是在哪里申请的

==54017== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==54017==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==54017==    by 0x40057E: func() (in /home/oceanstar/CLionProjects/Share/src/a.out)
==54017==    by 0x40058D: main (in /home/oceanstar/CLionProjects/Share/src/a.out)

最后这一段是总结,4字节为一块的内存泄露

==54017== LEAK SUMMARY:
==54017==    definitely lost: 4 bytes in 1 blocks
==54017==    indirectly lost: 0 bytes in 0 blocks
==54017==      possibly lost: 0 bytes in 0 blocks
==54017==    still reachable: 0 bytes in 0 blocks
==54017==         suppressed: 0 bytes in 0 blocks

编译程序2

 gcc -g -o ./a.out ./main.cpp

运用valgrind检测内存泄漏:

==55430== Memcheck, a memory error detector
==55430== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==55430== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==55430== Command: ./a.out
==55430== 
^C==55430== 
==55430== Process terminating with default action of signal 2 (SIGINT)
==55430==    at 0x4F25F70: __read_nocancel (in /usr/lib64/libc-2.17.so)
==55430==    by 0x4EB2B13: _IO_file_underflow@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==55430==    by 0x4EB3CE1: _IO_default_uflow (in /usr/lib64/libc-2.17.so)
==55430==    by 0x4EAE6B9: getchar (in /usr/lib64/libc-2.17.so)
==55430==    by 0x400592: main (main.cpp:11)
==55430== 
==55430== HEAP SUMMARY:
==55430==     in use at exit: 4 bytes in 1 blocks
==55430==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==55430== 
==55430== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==55430==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==55430==    by 0x40057E: func() (main.cpp:6)
==55430==    by 0x40058D: main (main.cpp:10)
==55430== 
==55430== LEAK SUMMARY:
==55430==    definitely lost: 4 bytes in 1 blocks
==55430==    indirectly lost: 0 bytes in 0 blocks
==55430==      possibly lost: 0 bytes in 0 blocks
==55430==    still reachable: 0 bytes in 0 blocks
==55430==         suppressed: 0 bytes in 0 blocks
==55430== 
==55430== For lists of detected and suppressed errors, rerun with: -s
==55430== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

可以看到,在head summary中,有该程序使用的总heap内存量,分配内存次数和释放内存次数,如果分配内存次数和释放内存次数不一致则说明有内存泄漏。

下面会有具体的分析:包括在main函数中和f函数中通过malloc申请了内存但是没有释放造成了多大的内存损失都标记有,–甚至行号都标记了,debug神器!

变形1:

#include <stdio.h>
#include <iostream>

int main()
{
    int *x;
    x = static_cast<int *>(malloc(8 * sizeof(int)));
    x = static_cast<int *>(malloc(8 * sizeof(int)));

    return 0;
}

报告是:

==59320== HEAP SUMMARY:
==59320==     in use at exit: 64 bytes in 2 blocks
==59320==   total heap usage: 2 allocs, 0 frees, 64 bytes allocated
==59320==        *********有几个没有释放就会有几个definitely lost*************
==59320== 32 bytes in 1 blocks are definitely lost in loss record 1 of 2
==59320==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==59320==    by 0x400691: main (main.cpp:7)
==59320== 
==59320== 32 bytes in 1 blocks are definitely lost in loss record 2 of 2
==59320==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==59320==    by 0x4006A2: main (main.cpp:8)
==59320== 
==59320== LEAK SUMMARY:
==59320==    definitely lost: 64 bytes in 2 blocks
==59320==    indirectly lost: 0 bytes in 0 blocks
==59320==      possibly lost: 0 bytes in 0 blocks
==59320==    still reachable: 0 bytes in 0 blocks
==59320==         suppressed: 0 bytes in 0 blocks
==59320== 
==59320== For lists of detected and suppressed errors, rerun with: -s
==59320== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

第3个例子: 使用未初始化的内存

#include <stdio.h>                                                              
int main()
{
    int x;
    if(x == 0)
    {
        printf("X is zero");
    }
    return 0;
}

  • Conditional jump or move depends on uninitialised value(s)
$ valgrind --tool=memcheck --leak-check=full ./Share 
==57052== Memcheck, a memory error detector
==57052== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==57052== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==57052== Command: ./Share
==57052== 
==57052== Conditional jump or move depends on uninitialised value(s)
==57052==    at 0x400549: main (main.cpp:5)
==57052== 
X is zero==57052== 
==57052== HEAP SUMMARY:
==57052==     in use at exit: 0 bytes in 0 blocks
==57052==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==57052== 
==57052== All heap blocks were freed -- no leaks are possible
==57052== 
==57052== Use --track-origins=yes to see where uninitialised values come from
==57052== For lists of detected and suppressed errors, rerun with: -s
==57052== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

第3个例子: 内存读写越界

#include <stdio.h>
#include <iostream>

int main()
{
    int len = 5;
    int *pt = (int*)malloc(len*sizeof(int)); //problem1: not freed
    int *p = pt;
    for (int i = 0; i < len; i++){
        p++;
    }
    *p = 5; //problem2: heap block overrun
    printf("%d\n", *p); //problem3: heap block overrun
   // free(pt);
    return 0;
}

problem1: 指针pt申请了空间,但是没有释放;
problem2: pt申请了5个int的空间,p经过4次循环(i=3时)已达到最后申请的p[4], 在i=4时p所指向的空间没有申请过; (下面valgrind报告中 Invalid write of size 4)
problem1: 同line8 (下面valgrind报告中 Invalid read of size 4 )

==58261== Memcheck, a memory error detector
==58261== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==58261== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==58261== Command: ./Share
==58261== 
==58261== Invalid write of size 4
==58261==    at 0x400707: main (main.cpp:12)
==58261==  Address 0x5a23054 is 0 bytes after a block of size 20 alloc'd
==58261==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==58261==    by 0x4006DC: main (main.cpp:7)
==58261== 
==58261== Invalid read of size 4
==58261==    at 0x400711: main (main.cpp:13)
==58261==  Address 0x5a23054 is 0 bytes after a block of size 20 alloc'd
==58261==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==58261==    by 0x4006DC: main (main.cpp:7)
==58261== 
5
==58261==   ****************这一段都是因为malloc但是没有free,如果free,就不会出现这个*******************
==58261== HEAP SUMMARY:
==58261==     in use at exit: 20 bytes in 1 blocks
==58261==   total heap usage: 1 allocs, 0 frees, 20 bytes allocated  
==58261== 
==58261== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1
==58261==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==58261==    by 0x4006DC: main (main.cpp:7)
==58261== 
==58261== LEAK SUMMARY:
==58261==    definitely lost: 20 bytes in 1 blocks
==58261==    indirectly lost: 0 bytes in 0 blocks
==58261==      possibly lost: 0 bytes in 0 blocks
==58261==    still reachable: 0 bytes in 0 blocks
==58261==         suppressed: 0 bytes in 0 blocks
==58261== ****************************************************************
==58261== For lists of detected and suppressed errors, rerun with: -s
==58261== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

 //--------------------如果没有出现堆内存泄漏,会打印-----------------
==58522== HEAP SUMMARY:
==58522==     in use at exit: 0 bytes in 0 blocks
==58522==   total heap usage: x allocs, xfrees, xxxx bytes allocated
==58522== 
==58522== All heap blocks were freed -- no leaks are possible

变形1:写越界

#include <stdio.h>
#include <iostream>

int main()
{
    int *x;
    x = static_cast<int *>(malloc(8 * sizeof(int)));
    x[9] = 0; //数组下标越界   Invalid write of size 4
    free(x);

    return 0;
}

变形2:读越界

#include <stdio.h>
#include <iostream>

int main()
{
    int *x;
    x = static_cast<int *>(malloc(8 * sizeof(int)));
    std::cout << x[9] ; //数组下标越界    Invalid read of size 4
    free(x);

    return 0;
}

第4个例子: 重复释放

#include <stdio.h>
#include <iostream>

int main()
{
    int *x;
    x = static_cast<int *>(malloc(8 * sizeof(int)));
    x = static_cast<int *>(malloc(8 * sizeof(int)));
    free(x);
    free(x);
    return 0;
}

报告:

==59602== Invalid free() / delete / delete[] / realloc()
==59602==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==59602==    by 0x4006FE: main (main.cpp:10)
==59602==  Address 0x5a230a0 is 0 bytes inside a block of size 32 free'd
==59602==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==59602==    by 0x4006F2: main (main.cpp:9)
==59602==  Block was alloc'd at
==59602==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==59602==    by 0x4006E2: main (main.cpp:8)
==59602== 
==59602== 
==59602== HEAP SUMMARY:
==59602==     in use at exit: 32 bytes in 1 blocks
==59602==   total heap usage: 2 allocs, 2 frees, 64 bytes allocated
==59602== 
==59602== 32 bytes in 1 blocks are definitely lost in loss record 1 of 1
==59602==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==59602==    by 0x4006D1: main (main.cpp:7)
==59602== 
==59602== LEAK SUMMARY:
==59602==    definitely lost: 32 bytes in 1 blocks
==59602==    indirectly lost: 0 bytes in 0 blocks
==59602==      possibly lost: 0 bytes in 0 blocks
==59602==    still reachable: 0 bytes in 0 blocks
==59602==         suppressed: 0 bytes in 0 blocks
==59602== 
==59602== For lists of detected and suppressed errors, rerun with: -s
==59602== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

第4个例子: malloc与delete释放问题

int main()
{
    char* str = (char*)malloc(5*sizeof(char));
    delete []str;
}

用malloc申请空间的指针用free释放;用new申请的空间用delete释放 (valgrind中Mismatched free() / delete / delete []);

==61950== Mismatched free() / delete / delete []
==61950==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==61950==    by 0x4006E8: main (main.cpp:8)
==61950==  Address 0x5a23040 is 0 bytes inside a block of size 5 alloc'd
==61950==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==61950==    by 0x4006D1: main (main.cpp:7)
==61950== 
==61950== 
==61950== HEAP SUMMARY:
==61950==     in use at exit: 0 bytes in 0 blocks
==61950==   total heap usage: 1 allocs, 1 frees, 5 bytes allocated
==61950== 
==61950== All heap blocks were freed -- no leaks are possible

第5个例子:内存覆盖

int main()
{
    char str[11];
    for (int i = 0; i < 11; i++){
        str[i] = i;
    }
    memcpy(str + 1, str, 5);

    char x[5] = "abcd";
    strncpy(x + 2, x, 3);
}

问题出在memcpy上, 将str指针位置开始copy 5个char到str+1所指空间,会造成内存覆盖。strncpy也是同理。

==61609== Source and destination overlap in memcpy(0x1ffefffe31, 0x1ffefffe30, 5)
==61609==    at 0x4C2E81D: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1035)
==61609==    by 0x400721: main (main.cpp:11)
==61609== 
==61609== Source and destination overlap in strncpy(0x1ffefffe25, 0x1ffefffe23, 3)
==61609==    at 0x4C2D453: strncpy (vg_replace_strmem.c:552)
==61609==    by 0x400748: main (main.cpp:14)
==61609== 
==61609== 
==61609== HEAP SUMMARY:
==61609==     in use at exit: 0 bytes in 0 blocks
==61609==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==61609== 
==61609== All heap blocks were freed -- no leaks are possible

#!/bin/sh
# $Id$
#
if [ -z "$1" ]; then
    echo "Usage: `basename $0` prog"
    exit 1
fi
valgrind --tool=memcheck \
--leak-check=full \
--time-stamp=yes \
--show-reachable=yes \
--track-origins=yes \
--trace-children=no \
--leak-resolution=med \
--track-fds=yes \
--log-file=myvalmem.log \
"$@"
  • –track-origins=yes表示开启“使用未初始化的内存”的检测功能,并打开详细结果。如果没有这句话,默认也会做这方面的检测,但不会打印详细结果。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

工具:valgrind学习 的相关文章

  • 删除字符串 C 的第一个字符

    我试图删除字符串的第一个字符并保留其余部分 我当前的代码无法编译 我对如何修复它感到困惑 My code char newStr char charBuffer int len strlen charBuffer int i 1 char
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • gtest 和 gmock 有什么区别?

    我试图理解的目的google mock Google 的 C 模拟框架 https github com google googletest blob master googlemock README md 我已经与gtest较早 但我还是
  • 基于 MS Bot Framework 中的响应分支对话框/表单

    我们正在尝试使用 MS Bot Framework 但尚未完全弄清楚如何实现此场景 我们有一个 LUIS 对话框 类型 它工作正常并且经过适当的培训 以常见的三明治为例 LUIS 意图寻找的基本内容是用户询问订单状态 如果问题中提供了订单号
  • 将列表(对象)转换为列表(字符串)

    有没有办法转换List of Object to a List of String 在 c 或 vb net 中而不迭代所有项目 幕后迭代很好 我只想要简洁的代码 Update 最好的方法可能就是进行新的选择 myList Select f
  • C++ 私有静态成员变量

    此 C 代码在编译时产生链接器错误 A h class A public static void f private static std vector
  • 'goto *foo' 其中 foo 不是指针。这是什么?

    我正在玩标签作为值 https gcc gnu org onlinedocs gcc Labels as Values html并最终得到这段代码 int foo 0 goto foo 我的 C C 经验告诉我 foo means dere
  • async wait 在调用异步方法时返回 Task> 而不是 List

    我正在尝试了解 async wait 的用法 并且研究了一些博客文章 现在我已经编写了一个测试代码 但它没有按照我期望的方式工作 我有一个返回列表的方法 private List
  • 使用成员作为实现者来实现接口

    我有实现 IA 的 A 类 现在我需要创建也应该实现 IA 的类 B B 类有 A 类的实例作为成员 有什么方法可以定义A的实例实现B类中的IA吗 interfase IA void method1 void method2 void me
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 如何附加到 xml

    我有这个xml
  • 如何用C++解析复杂的字符串?

    我试图弄清楚如何使用 解析这个字符串sstream 和C 其格式为 string int int 我需要能够将包含 IP 地址的字符串的第一部分分配给 std string 以下是该字符串的示例 std string 127 0 0 1 1
  • 为什么C++变量是指针时不需要正确定义?

    我对 C 语言完全陌生 特别是指针 经验主要是 PHP 并且希望对以下内容进行一些解释 我已经尝试寻找答案 这两行代码如何能够在我的程序中完成完全相同的工作 第二行似乎违背了我迄今为止所学到和理解的关于指针的一切 char disk 3 D
  • .Net Core 中的脚手架以及解决方案中的多个项目

    我创建了一个针对 net461 的 Net Core MVC6 应用程序 我使用了一个我非常熟悉的项目结构 其中我将数据 模型和服务类放置在单独的类库项目中 并且 Web 项目引用这些项目 当我尝试搭建控制器时 我收到一条错误 指出我正在搭
  • C 的“char”使用什么字符集? [复制]

    这个问题在这里已经有答案了 简单的问题 我最近开始用 C 编程 有一个简单的问题 C 编程语言在其 char 类型中使用什么字符集 例如 ASCII 还是取决于软件 操作系统 char 本质上是 1 个字节 主要在所有操作系统上 所以默认情
  • Qt:将拖放委托给子级的最佳方式

    我在 QWidget 上使用拖放 我重新实现了 DragEnterEvent dragLeaveEvent dragMoveEvent 和 dropEvent 效果很好 在我的 QWidget 中 我有其他 QWidget 子级 我希望它们
  • 如何从代码隐藏中向我的 div 添加点击事件?

    如何从代码隐藏中向我的 div 添加点击事件 当我点击 div 时 会出现一个消息框 其中显示 您想删除它吗 并在框中显示 是 或 否 全部来自后面的代码 while reader Read System Web UI HtmlContro
  • 需要使用 openssl 加密和解密文件的示例 C 代码

    我正在用 Linux C 编写代码 我需要使用以下命令来加密和解密文件 openssl 目前 我使用系统命令 des3 e nosalt k 0123456789012345 in inp file out out file 进行加密 使用
  • 如何使用简历实现一个“一网打尽”的异常处理程序?

    我想知道我怎样才能写一个抓住他们全部应用程序级别的异常处理程序将为用户提供恢复应用程序流程的选项 如果您正在运行 Windows 窗体应用程序 将处理程序添加到Application ThreadException event
  • 如何将 char 转换为 unsigned int?

    我有一个字符数组 它实际上用作字节数组 而不是用于存储文本 在数组中 有两个特定字节表示我需要存储到无符号 int 值中的数值 下面的代码解释了设置 char bytes bytes 2 bytes 0 0x0C For the sake

随机推荐

  • Apache Hive+Kerberos安装配置及 Kettle(Pentaho)访问带 Kerberos 认证的 Hive的集成

    目录 1 连接 2 KDC 安装 2 1 安装 Kerberos 服务 2 2 配置 var kerberos krb5kdc kdc conf 2 3 配置 var kerberos krb5kdc kadm5 acl 2 4 配置 et
  • Java从后台重定向(redirect)到另一个项目的方法

    1 通过ModelAndView跳转 RequestMapping alipayforward public ModelAndView alipayforward HttpServletRequest req HttpServletResp
  • uview基本配置,在HubildX中如何配置uni-app相关的组件

    配置步骤 1 引入uView主JS库 在项目根目录中的main js中 引入并使用uView的JS库 注意这两行要放在import Vue之后 main js import uView from uview ui Vue use uView
  • 重心坐标

    数学中 重心坐标是由单形 如三角形或四面体等 顶点定义的坐标 重心坐标是齐次坐标的一种 设 v1 vn 是向量空间 V 中一个单形的顶点 如果 V 中某点 p 满足 那么我们称系数 1 n 是 p 关于 v1 vn 的重心坐标 这些顶点自己
  • utf-8 中的一个汉字占几个字节

    原文链接 http blog csdn net chummyhe89 article details 7777613 占 2 个字节的 占 3 个字节的 基本等同于 GBK 含 21000 多个汉字 占 4 个字节的 中日韩超大字符集里面的
  • R手册(Common)--tidyverse+tibble

    tidyverse是一系列包的组合 构建了一套完整的数据分析生态链 提供了一套整洁的数据导入 分析和建模方法 刷新了R语言原有的数据科学体系 文章目录 tidyverse Usage core tidyverse packages Impo
  • 【HBZ分享】ClickHouse数据结构 之 LSM-TREE

    ClickHouse高性能写入剖析 LSM Tree数据结构 简介 先了解一组测试数据来对比磁盘的 随机读写 与 顺序读写 的性能差距 顺序读写 磁盘的顺序读写 磁头基本不需要换道 即使换道 时间也是极短的 性能极高 比如0 03 2000
  • 转移到ios下载安卓_转移到ios下载-转移到ios app下载v2.10.0 安卓最新版-2265安卓网...

    转移到ios app是一款非常好用的手机换机app 用户可以通过该软件把安卓手机的文档和数据完美的转移到ios中 不用担心换手机后数据丢失 并且该软件操作简单 有需要的可以到2265安卓网下载体验 转移到ios介绍 Move to iOS
  • easypoi 导出合并表头,合并单元格 遇到的坑

    大家肯定都知道 easypoi 但是不知道有没有用过 我也是第一次用 常规导出确实非常简单 在字段上 加注解 Excel name 序号 isColumnHidden true orderNum 0 fixedIndex 0 进行排序就可以
  • Python用turtle库绘制图形——漂亮的玫瑰

    一 漂亮的玫瑰简笔画图片 图1的漂亮的玫瑰简笔画图片是从 百度图片 下载的一幅玫瑰图片 画得很漂亮 但只是黑白色 且没有画花萼 萼片 图1 漂亮的玫瑰简笔画图片 二 绘制玫瑰的方法 花叶 花梗用形状 圆弧和直线 绘制 并填色 叶片上的锯齿状
  • Android Paint之函数大汇总

    作者 as pixar 链接 https www jianshu com p 34536b1bdbf9 来源 简书 一 函数 含义 基本用法 reset 重置画 setColor int color 给画笔设置颜色值 setARGB int
  • 基于RBM-DBN深度学习网络的数据分类matlab仿真

    基于RBM DBN深度学习网络的数据分类matlab仿真 深度学习在计算机视觉 语音识别 自然语言处理等领域中取得了重大的进展 其中 RBM DBN Restricted Boltzmann Machine Deep Belief Netw
  • 解决PowerDesigner中Name与Code同步的问题。

    PowerDesigner中 但修改了某个字段的name 其code也跟着修改 这个问题很讨厌 因为一般来说 name是中文的 code是字段名 解决方法如下 1 选择Tools gt GeneralOptions 菜单 出现General
  • mybatis的接口绑定方式(注解绑定和配置xml文件)

    目录 一 配置xml文件 步骤 1 创建pojo类 Student对象 2 创建StudentMapper接口 3 创建mapper xml配置文件 4 在mymybatis config xml中添加StudentMapper配置 5 创
  • at指令集

    AT指令中文手册 2 1 简介 5 1 1 名词术语 5 1 2 AT 命令简介 5 2 AT 命令祥解 5 2 1 一般命令 5 2 1 1 AT CSCS 选择TE 字符集 2 7 补充业务命令
  • python中判断整数和整型的方法

    我们先看一下什么整数和整型 整数 integer 是正整数 零 负整数的集合 整型 计算机中的一个基本的专业术语 指没有小数部分的数据 来这百度百科 猛一看整数和整型没有区别 所以网上有一堆使用使用isinstance来判断一个数是否是整数
  • 【Java】抽象类和接口

    并没有那么多天赋异禀 优秀的人总是努力翻山越岭 目录 1 抽象类 1 1 抽象类的概念 1 2 抽象类的语法 1 3 抽象类的特性 1 4 抽象类的作用 2 接口 2 1 接口的概念 2 2 接口的语法规则 2 3 接口的使用 2 4 接口
  • windbg调试驱动不用替换调试机器驱动的方法

    开发windows驱动 通常调试驱动的方法是在主机上编写代码编译通过 将sys和inf拿到被调试机台上安装测试 主机通过windbg连上调试机台 当代码有改动时 将编译好的驱动再拿到被调试机台上安装测试 每次都拷贝到调试机台上安装驱动这个动
  • 报错jinja2.exceptions.UndefinedError: ‘form‘ is undefined

    这是我在写flask项目时报的错误 报错原因 是因为两个视图函数引用了同一个模板 模板中使用了jinja2 其中一个视图函数没有使用其语法 所以报了以上错误 解决方法 只需要把两个视图所引用的模板分开写就可以了
  • 工具:valgrind学习

    Valgrind手册 Quick start 文章目录 概述 体系结构 Valgrind 原理 安装 编译时需要注意 快速入门 LEAK SUMMARY 内存泄漏总结 分类 实践 第一个例子 没有内存泄漏 第二个例子 只申请内存而不释放 编