
c/c++
文章平均质量分 54
猿来是码农
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
relocation R_X86_64_32 against `.bss‘ can not be used when making a PIE object
原因是在编译json_value.o 和 json_write.o 时,没有添加编译选项 -fPIC,这个编译选项用于生成位置无关代码(Position Independent Code)。当构建共享库或PIE时,需要确保所有代码都是位置无关的,以便它们可以在任何内存地址上加载和执行。原创 2024-12-27 16:00:03 · 576 阅读 · 0 评论 -
c/c++ *和后置++的优先级
实际结果是不一样的,其实我们分析一下可以得出后置++优先级高于*,分析如下:*p++ 先计算了p++,然后再解引用,因为后置++在当前情况下可视为不变的,等你再用它的时候它才是+1后的结果,所以添加了 printf("*p = %d\n", *p);而 (*p)++ 是解引用后再++了,是 array[0]+1 = 1 + 1 = 2 了。所以 *p++ 和 *(p++) 是一样的。我看到网上有人说这个 *p++ 中 * 优先级比较高,说是先解引用了,再把指针++,真是这样的吗?原创 2024-09-10 17:30:17 · 485 阅读 · 0 评论 -
c/c++ 指针数组
strName 是解引用,所以输出是 “123” ,而 *strName + 1 为什么输出是 “23” 呢?原创 2024-09-06 16:20:32 · 436 阅读 · 0 评论 -
const 指针
编译选项都是一样的:-Wall -g ,然而c语言编译是没有警告提示的,而c++则给出一个警告:warning: ISO C++ forbids converting a string constant to ‘char*。c++执行了更严格的编译规则。那警告很明显是说明了 c++标准禁止将字符串常量转换为 char*,因为字符串常量是只读的,而 char* 类型的指针是可以修改指针指向的内容的,所以它两个冲突了。正确的定义应该是这样:const char *str = "abcdefg";原创 2024-09-05 14:12:55 · 375 阅读 · 0 评论 -
c/c++ 打印调用栈
然后可以把这个函数放在信号回调函数里,所以先需要设置一下信号处理函数,函数:int sigaction (int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact),打印调用栈可以在程序出现死机的时候(如出现 SIGABRT、SIGSEGV等一些信号错误)是很有用的信息,有可能就不需要 core file 来协助排查问题了。原创 2024-07-13 16:19:00 · 975 阅读 · 0 评论 -
c++ new 与二级指针
跟第一个例子有点像,第一个例子里的 int *p = new int[MAX_ARRAY_NUM];可以理解为申请了一个MAX_ARRAY_NUM 个连续的 int 型内存地址,p 指向了首地址处。而这里的 int **p = new int*[MAX_ARRAY_NUM];这样定义出来的就是一个常量的指针数组,而用 new 出来的就如上面的 int **p = new int*[MAX_ARRAY_NUM];释放内存自然就是对应的。原创 2024-07-11 15:13:24 · 354 阅读 · 0 评论 -
errno 和 strerror函数
到这里我们已经知道函数 strerror() 是怎么实现的了,而且也知道函数使用方法也是对的,但为什么会出现 Segmentation fault 呢?原因是没包含头文件,导致 strerror() 函数变成隐式声明了,而隐式声明的函数它的默认返回值是 int 类型(没找到C语言关于这点的说明文档,有同学知道的话烦告知一下),所以用 %s 打印 int 类型导致 segmentation fault 了。搞得我还去看了源码,顺便学习了一下 errno,原因后面再讲到。原创 2024-03-06 19:01:35 · 679 阅读 · 0 评论 -
指针数组初始化,不常见啊
这里很明显定义了一个指针数组,也就是首先 _sys_errlist_internal 是一个数组,并且这个数组里元素都是指针,所以它是一个指针数组毫无疑问。所以这种初始化方式应该是指定元素的初始化方式,未初始化到的元素是空的(指针类型时是null,其他类型未验证)。因为没有指定数组大小,所以这样初始化数组大小是多少呢?从 C 语言数组类型知识点我们应该能猜出来,数组大小应该是 6,即包含 6 个元素。在 errlist.h 头文件里使用了宏定义,然后完成对指针数组的初始化。原创 2024-03-06 17:08:07 · 584 阅读 · 0 评论 -
关于 passing ‘const xx’ as ‘this’ argument of 的错误
编译错误应该跟开头那个是一样的意思。结合书上说的 const 函数旨在不修改类的成员,而 auto set = mLdpIdmMap[ldpIdx];以前看书的时候,书上说是如果在函数后面加上 const 表明这个函数不会去修改类成员,光从这个函数来看确实没有修改成员,但为何需要声明为 const 才能编译过呢?解决办法当然就是去掉函数的 const 声明,或者是用 map 的 find() 接口,用 find() 接口更合适,因为本意是想使用 map[key] 的值,结果却多出一个默认的元素值。原创 2023-10-19 20:02:03 · 650 阅读 · 0 评论 -
centos7 编译bluez ARM版本及undefined reference to `g_thread_new‘
我下载的是2.40.0 版本的:wget http://ftp.acc.umu.se/pub/GNOME/sources/glib/2.40/glib-2.40.0.tar.xz。简直要崩溃啊,那我编译的 glib-2.30.0 版本不是白白浪费我的时间了吗?此处有很多草泥马路过!于是下载了好几个版本的 glib,最后皇天不付有心人啊,真的是版本过低了,真想干死这个 glib。解释得很到位,这里我就直接修改Makefile 了,把那个高度的编译选项删掉。历尽千辛万苦,最后编译 bluez 也终于成功了。原创 2023-06-01 22:12:26 · 687 阅读 · 0 评论 -
一个简单的c程序
其实就是被截断后的值,因为 300 的二进制为 0001 0010 1100(前面的0就不列了),而 char 只占 8 位,所以只会把低 8 位赋给了 a (即0010 1100,其十进制就是44);从上面的输出我们也可以得出,如果是以无符号方式输出则其二进制是多少其值就是多少,而以有符号输出,因其最高位是 1,表示负数,则其二进制是以补码方式存储的,要输出其十进制则需要还原为原码。这里又涉及到原码、反码、补码的知识点了,有兴趣的可以看这篇。上面这样的二进制是错的,因为我使用的是机器是小端的存储方式。原创 2023-05-23 14:58:44 · 725 阅读 · 0 评论 -
c++模板和c的混用
工作中虽然用的都是 cpp文件,但里面大部分还是c接口,即全局接口。定义了很多的结构体,然后最终的目的是要把各个结构体里的 OutLifOidx 和 OutLabel 取出来。注意这个模板的实现需要在 extern "C" 外面,否则编译会出错的。原创 2023-04-18 16:44:20 · 163 阅读 · 0 评论 -
inet_ntop 函数崩溃问题
就算没有包含原型声明,但在运行时链接的动态库里的函数,应该也是没问题才对啊,那为什么不包含头文件运行起来会出现段错误呢?这里不明白为什么返回值是 int 类型呢?然后我发现,代码里没有包含头文件:,man 的时候看到的。今天在看TCP/IP 协议时看到一段代码,于是就拷贝下来自己编译运行一下,结果出现一个segmentation fault,这是一个奇怪的现象,奇怪在哪里呢?这是一个服务端代码,编译没有问题,这段代码主要工作就是:接收到客户端的字符后,转换成大写再发给客户端。原创 2023-03-22 19:37:08 · 580 阅读 · 0 评论 -
map与数组的使用
这里添加数据用到了2种方法,一个是[]操作符,一个是insert()函数。而输出打印则用了一个c++11版本的for循环:for(auto it : data),这样的话,it 就是一个 std::pair 类型,其 first 就是对应 std::string类型的key值, second 就是对应MapData 的 value值。今天公司领导突然给了一个任务,使用到的map和数组,进公司快一年了,一直用的是c,c++似乎很久没用过了,这里记录一下。原创 2023-03-07 21:56:27 · 611 阅读 · 0 评论 -
智能指针shared_ptr 的 reset使用
可以看到 Foo::bar = 100, use_count() = 2,此时两个智能指针都管理着 0x1029028 的资源,当调用 sptr1.reset();后,这个资源就少了一个管理者,所以 After reset(): use_count() = 1, sptr = 0x1029028,当离开作用域后,此资源才被释放。可以看到在调用 reset() 后,调用了对象的析构函数进行释放。带删除器的版本只会用在数组对象释放的情况,如果是数组对象的情况下不用删除器,则行为是未定义的。原创 2023-02-07 15:55:24 · 12812 阅读 · 1 评论 -
c++ map operator[]
后会发现,当用 [k] 操作时,如果 k 与容器中任何元素的键不匹配,该函数将插入一个具有该键的新元素,并返回对其映射值的引用。注意,这总是将容器大小增加1,即使没有为元素分配映射值(使用默认构造函数构造元素)。这句本来的目的是想访问 key = 3 的元素,结果意外的插入了一个新的无比,其值为0。如果是其他基本类型 float, double, char 呢?map 的 operator[] 不仅是简单的下标方式访问元素,还可以修改元素,甚至可以插入新元素。如果是std::string类型呢?原创 2023-02-02 22:51:28 · 516 阅读 · 1 评论 -
c++11 枚举enum
类似于 class 中的继承的语法,这里的作用是限制了 enum 元素的最大值,如上 DEV_D 的最大值就是 255,如果赋值大于 255 会怎样呢?编译错误,因为这个main作用域内已经有了一个枚举类型值 red。这样用有什么好处----限制了枚举的变量的作用域。如果没有这个作用域是怎样的呢?看到 c++11 中 enum 的两个新用法,记录一下。有了枚举类限定了枚举类型的作用域,减少了命名空间的冲突。1,限制枚举变量值大小。原创 2023-02-01 22:27:50 · 367 阅读 · 0 评论 -
模板特化与static成员初始化
这里会比普通的类的 static 成员初始化多了: type template Singleton ,这样就表明这个成员是类模板里的成员,而非普通类的成员。而如果遇到这个是特化的模板呢?我们知道在 c++ 的类中,如果有static成员数据,则需要在类外进行定义,而类内那只是声明。这个在类模板中也是一样的,需要在类外进行定义。这个错误看不懂是什么原因,直接翻译过来就是:显式专用类的成员是在没有模板头的情况下定义的。感叹C++语法真是太奇妙了^_^原创 2023-01-12 17:04:32 · 631 阅读 · 0 评论 -
pthread_once 实现的单例
在多线程下第一次被调用时,会调用 init_routine 函数指针所指向的函数,之后再调用时,不会再调用这个函数指针指向的函数。创建两个线程,调用的是同一个线程函数,在函数里调用Singleton::instance();两个线程先后调用了 instance() 函数,但其中的 pthread_once() 中的 init_routine 仅执行了一次。常用于多线程开发中,它的用途是确保在一个进程下的多个线程调用它时,某个资源只被初始化一次。原创 2023-01-12 15:58:49 · 487 阅读 · 0 评论 -
mongoose 的打印改造
可以看到宏 MG_LOG(level, args) 是分为两段的,第一段前缀相当于是固定的,第二段是用户实际要输出的内容,我们只看第一段就可以了。其前 2 列表示什么一看是看不出来的,需要看代码,后几列无非就是文件名、行号、 函数名以及实际用户要输出的内容。于是就有了这篇文章,改造它这个打印输出格式。注意上面的 buf 的长度是64 字节,如果有函数名特别长那输出可能就被截断了。while 循环那里就是填充空格,我这里最多只填充5个空格,太多也不好看,原创 2022-12-16 15:53:50 · 757 阅读 · 0 评论 -
c++ enable_shared_from_this
智能指针 ptr1 和 ptr2 的引用计数都是 1,说明它们指向的不是同一个资源(这里可能会有人疑惑两个智能指针指向同一个地址,怎么引用计数没有增加呢?类 A 中有一个函数 getSharedPtr() 函数,用于返回指向当前对象的一个智能打针,就是用 this 构造了一个智能指针进行返回,我们看一下这样会不会有问题呢?我们看到,两个智能指针的引用计数都为2,这两个智能指针指向了相同的资源,在 main 函数退出后,两个智能指针释放,引用计数变为 0,资源释放正常。执行没有异常,那这样用是正确的吗?原创 2022-11-26 15:42:35 · 3023 阅读 · 0 评论 -
c++11 unique_lock 使用
mutex 的 lock 和 unlock 完全是自动的,无需我们手动操作。因为模板类 lock_guard 在构造函数里进行了 lock,在析构函数里进行了 unlock。和 lock_guard 具有同样功能的还有一个:unique_lock。同样的,unique_lock 也是可以自动锁定和解决,但其多了几个接口,且构造函数里也多了一些参数。很简单,子线程先获取锁,执行完后 main 线程获取锁,这里完全靠自动锁定和解锁。2,构造函数里参数 std::defer_lock。3,lock() 函数。原创 2022-11-25 17:35:03 · 2051 阅读 · 0 评论 -
std::logic_error 错误的解决
从函数调用栈上看,程序是在这个函数里崩溃的,一行行代码看下来,那只有getenv那两行代码可能存在问题了,这里用 getenv 返回的 char 指针构造一个 std::string,假如这个 getenv() 返回 NULL 指针,这个不就有问题了吗?这个应该是 std::string 相关的一个错误,具体的错误信息还得用 GDB 跟踪一下了。看第 8 栈帧已经是系统库里的东西了,第 9 帧是我本地的代码,于是只能查看代码了。原创 2022-11-06 22:59:28 · 2677 阅读 · 0 评论 -
c/c++ 中的标签
但当我仔细看 create 函数时,没发现有问题,如果函数里调用其他函数有错误而跳到error_label处的话应该还有其他打印的,但是没发现。当我想多加打印进行调试时,突然想到这个标签前没有 return 啊,这个标签后的语句是会顺序执行下去的。所以在 delete 函数里检测到指针是 null时,用例才失败的,因为在 create 函数里,标签 error_label 后的语句是删除该指针。,老代码中到处都是goto和标签,然而今天在跑测试用例时却失败了,这个错误就是和标签有关,记录如下。原创 2022-10-26 16:55:02 · 495 阅读 · 0 评论 -
muduo库的Stock例子
对于两个函数 testLongLifeFactory() ,上面 3 个头文件那样使用都是没有问题的,因为 testLongLifeFactory() 函数里 StockFactory 对象于 stock 析构之后才析构,在函数 static void weakDeleteCallback(const std::weak_ptr &wkFactory, Stock *stock) 里使用是没有问题的。1,shared_from_this ,是线程安全,只是会延长对象的生命期。原创 2022-10-24 18:39:22 · 513 阅读 · 0 评论 -
主线程退出,子线程会退出吗?子线程崩溃,主线程会退出吗?
大部分情况子线程就没有执行起来,偶尔会有一次子线程执行了。可以看到进程结束了,没跑用例前我以为子线程崩溃主线程不会有影响,但是错误的。因为这里涉及到了信号的处理行为,子线程产生的信号应该也算是此进程产生的信号,那信号对应的处理方式是什么呢?若是主线程调用 pthread_exit() 进行退出,则其创建的子线程会继续执行,直到整个进程终止。pthread_exit 函数会终止调用线程,但在线程终止时,进程共享资源不会被释放,只有进程中的最后一个线程终止时,进程共享资源才会释放。原创 2022-10-11 16:19:03 · 2133 阅读 · 1 评论 -
mongoose 文件上传-表单形式
这个得根据实际情况进行输入,如果程序是在本机运行,同时你也是通过本机的浏览器的话,这样输入是没问题的。而我的实际情况是,程序在CentOS 服务上运行,但我是在 Window10 是操作文件上传,则这个地址中的 localhost 要相应地修改在 CentOS 服务器的地址。event type = 2,查看代码是 MG_EV_POLL 事件,属于正常的,但访问时为何没有连接的反应呢?这个例子只合适上传一般的文本文件,像其他的二进制的文件是用到了其他的例子,这里不作介绍。原创 2022-09-18 23:31:22 · 1490 阅读 · 0 评论 -
c++ 线程类
可以看到在 createThread() 成员函数里调用了 pthread_create() 进行线程的创建,而且线程函数是此类的一个 static 函数 startThread(void* arg),为什么是 static 类型函数呢?现在C++11及之后版本已经提供了线程类来使用线程,但我们在编译的时候还是需要添加 -lpthread 链接(也许其线程类实现还是得依赖 pthread 库吧,没看过源码还不清楚),那如果不使用c++提供的线程类,我们在实际项目中是如何封装的线程类呢?原创 2022-09-15 10:44:08 · 1623 阅读 · 0 评论 -
函数指针模板
我们一般声明的函数指针,如:void (*funcPro)(int),那用这个函数指针类型定义的变量,可以指向一个“返回值是 void,带一个 int 类型的参数的函数”。这些宏最终的目的是把 两个参数连在一起,即经过 BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) 后,BOOST_FUNCTION_FUNCTION=functionBOOST_FUNCTION_NUM_ARGS,而这个 BOOST_FUNCTION_NUM_ARGS 是一个宏,那这个宏是什么呢?原创 2022-09-14 22:11:19 · 1260 阅读 · 0 评论 -
模板的全局特化
模板的特化简单地理解就是明确参数的类型,而不是用 typename , 不管是函数模板,还是类模板,都可以实现特批。其语法为:template xxx,模板参数是空的。原创 2022-09-13 19:15:19 · 543 阅读 · 0 评论 -
线程私有数据__thread
变量 tCachedTid 是缓存了调用线程的线程id,当有线程调用 CurrentThread::tid() 时,第一次会调用系统调用,然后线程id缓存在了 tCachedTid,此线程再调用 CurrentThread::tid() 时,即从缓存数据里直接取,避免每次都调用系统调用,提高效率。是依赖于 pthread 库实现的,而今天介绍的这个则是 gcc 提供的标识符:__thread,它只能用于修饰 POD 类型,不能修饰复合类型,如struct, class。原创 2022-09-13 14:39:02 · 240 阅读 · 0 评论 -
popen 函数的使用,获取不到执行结果
通过查看 man 手册知道,成功执行时,文件流会输出到标准输出,但似乎没提到错误的情况,那这个错误会不会输出到标准出错上了呢?如果是的话,那它应该也是输出到标准输出了啊,这里为什么拿不到结果呢?但又想到,如果popen()执行出错,信息被输出到标准出错的话,那我们是不是可以重定向,把标准出错重定向到标准输出呢?最近在调试代码的时候,发现一个问题,在CentOS 服务器调试好好的代码,结果到了嵌入式上,居然出现异常了,因为有些命令在嵌入式设备上被裁掉了。可以看出,程序执行的结果和命令执行的结果是一样的。原创 2022-09-03 19:27:18 · 4040 阅读 · 2 评论 -
http 协议目录操作--mongoose
其实这个参数最主要关心两个成员:opts.document_root 和 opts.enable_directory_listing。前几篇文章已经介绍了文件的下载与上传,操作的都是文件,而如果是操作目录呢,应该怎么做呢?这里只是简单地处理了目录和普通文件的区别,还有其他如字符设备文件、块设备文件、链接文件、socket 文件这里不作处理。这样就得出了 compile 的相对路径了,那程序本身就可以访问这个目录。就是用来设置目录的,我们可以简单看下这个函数做了什么。这样目录操作就已经正常了。原创 2022-09-02 19:17:47 · 996 阅读 · 0 评论 -
http 协议文件上传异常处理--mongoose
接着上一篇说到的,在发送文件数据前服务端出错了,且回应了,客户端应该不进行数据的发送。这里演示一种情况:指定的目录不存在,服务端应答"no suce directory",然后关闭连接。这样操作似乎是可以了,但奇怪的是,同样的代码我在嵌入式设备上测试时,结果跟这个不一样,操作嵌入式设备,文件也会传输,同时 postman 取不到应答消息,不知为何?实际能得到的结果是,客户端(postman)确实没有发送数据。原创 2022-09-02 09:29:50 · 1531 阅读 · 0 评论 -
http 协议文件上传 - mongoose
MG_EV_HTTP_PART_BEGIN 事件时,可以获取到上传过来的文件名,MG_EV_HTTP_PART_DATA 事件时,可以获取到文件数据,所以这两个就是创建一个文件,然后往里面写数据,在 MG_EV_HTTP_PART_END 时,关闭文件,回复消息给客户端,然后断开连接。这几个事件类型,MG_EV_HTTP_PART_DATA 会调用多次,取决于上传的文件大小,及一次最大读取数据的大小(即:MG_TCP_IO_SIZE),其他的事件类型只调用一次。时调用,即 uri=/fileUpload。.原创 2022-09-01 15:18:26 · 2046 阅读 · 0 评论 -
http 协议大文件下载
响应的正文只能通过http响应消息进行传输,如果是小文件(比如小于1M)传输,则没有什么问题,直接把文件内容加载到正文进行回应即可,但如果是大文件(比如大于10M),不可能把文件内容加载到正文吧,如果更大的文件呢,100M?下载一个 19 M 的文件是可以成功的,再大的文件没有试,因为下载速度有点慢。那下载下来的文件是否有异常呢?windows上下载的,所以把这个文件拷贝到 CentOS 服务上看一下了,这两个文件经过 md5sum 后值是一样的,那我们下载的文件就是正常的。那用c++代码怎么写呢?....原创 2022-08-31 23:25:51 · 5427 阅读 · 0 评论 -
http 协议之 Content-Type
Content-Type 字段是 http 服务端返回给客户端时,head 里面带上的,这个字段表明服务端返回给客户端的 body 是什么类型的,然后客户端就可以根据这个类型进行文件处理。如浏览器客户端,针对 text/html 类型时,是直接显示或解析成网页进行展示,针对 image/jpg 时,浏览器会展示成图片,针对 audio/mpeg 类型时,就当成音频播放,针对 video/mp4 类型时,就当成视频来播放。此类型即为可读类型,text 文本时,直接显示,html 时,网页显示。......原创 2022-08-29 21:49:44 · 6010 阅读 · 2 评论 -
mongoose 源码解读(一)
在上一篇文章中,我们提到 mg_mgr_poll 函数里其实调用的是 select 系统调用,最终调用的是这个函数:time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms);而这个函数里会进行各种判断,这里我只关心发送,即写事件。函数 mg_if_can_send_cb()执行完成一次,发送缓冲区里还有数据,则 poll()里会再次触发 write 事件,然后再循环调用 mg_if_can_send_cb()函数,直到把数据发送完毕。.原创 2022-08-28 17:13:44 · 2287 阅读 · 2 评论 -
mongoose 应用程序开发流程
这个初始化函数最主要的工作是指定的与 socket 相关的函数接口,如 listen、poll、connect、send、recv 等函数,这些函数才是真正操作 socket 的函数,而我们代码里调用的一些发送接口,如:mg_send() 接口只是把数据发送到 mg_connection 的缓冲区,前面的 send 接口才是真正发送数据的。poll 函数指针指向的是这个函数 mg_socket_if_poll(),函数里调用 select() 系统调用。这些函数指针的调用就是调用上面定义的那些函数了。...原创 2022-08-27 23:44:52 · 978 阅读 · 0 评论 -
mongoose 搭建 http 服务 -- 编译
编译 32 位 json 库也很简单,修改其目录下的 Makefile,添加编译选项 -m32 即可编译出 32 位的库了。所以只能编译 32 位的程序了,修改Makefile ,添加编译选项 -m32 可以编译 32 位程序。libssl.a 和 libssl.so 静态库和动态库是有的,但都是 32 位的。Makefile 里添加库路径及库名称:-L../json -ljson。json库明明是有的,结果一看是 64 位的。3,没有编译 mongoose.c 问题。6,json 库找不到的问题。....原创 2022-08-26 19:31:52 · 935 阅读 · 0 评论