阿杰,我给你整理一份 strdup 函数详解,包括概念、用法、返回值、注意事项和示例。 一、概念函数原型(C 标准库):char *strdup(const char *s);作用:复制一个字符串 s 并在堆上分配新内存,返回新字符串的指针。 ; char *copy = strdup(original); // 复制字符串 if (copy == NULL) { printf("内存分配失败\n"); 四、注意事项动态内存:strdup 在堆上分配内存,需要 手动释放(free())。 :复制字符串并返回新堆内存指针关键点:strdup 自动分配内存并复制字符串需要 free() 释放内存POSIX 环境下可直接使用,Windows 用 _strdup()替代方法:手动 malloc
quote && *q == ' ') { *q = '\0'; //strdup会在堆上分配空间,返回这块堆内存的指针 argv ; } q++; } argv[argc++] = strdup(tmp); for (i = mCommands->begin(); i ! 前15个参数的处理过程中,argv数组中的元素都是正常的从strdup返回的指向堆的指针值,即指向参数字符串的指针。 这里需要说明下strdup这个函数。char* strdup(const char *s1)函数会为s1指针指向的字符串数据分配等大小的内存,并返回指向这块内存的指针。 当用户进程第2次调用dispatchCommand,走到argv[0] = strdup(tmp)处时,strdup分配的内存就是上次释放掉的FrameworkCommand所在内存,并把tmp的字节数据拷贝到这块内存中
#0 0x00007ff84abb5721 in __strlen_sse2_pminub () from /lib64/libc.so.6 #1 0x0000000000440bcc in my_strdup (PSI_NOT_INSTRUMENTED, cur[0], MYF(MY_WME)); part_username = my_strdup(PSI_NOT_INSTRUMENTED, strtok(cur[0], "@"), MYF(MY_WME)); (void)mysql_fetch_row(result); // Read eof } } my_strdup在my_sys 下一个工具函数 char *my_strdup(PSI_memory_key key, const char *from, myf my_flags) { char *ptr; size_t (PSI_NOT_INSTRUMENTED, user, MYF(MY_WME)); part_username = my_strdup(PSI_NOT_INSTRUMENTED
: strcmp 字符串比较 strlen 计算字符串长度 strstr 字符串查找 memcmp 内存比较 strcpy 字符串拷贝 memcpy 内存拷贝 本篇文章介绍下面几个函数: strdup strchr 字符查找函数 (从头开始) strrchr 字符查找函数(从尾开始) strcat strncat 字符串拼接函数 memset 内存初始化函数 (可用于赋初值) 二、重写函数源码 2.1 strdup 字符串拷贝函数 strdup是字符串拷贝函数,一般要配合free使用,因为内部会申请空间存放新的字符串。 char * strdup(const char *s) { char *new; if ((s == NULL) || ((new = malloc (strlen(s) + 1))
g_hash_table_new_full(g_str_hash, g_str_equal, free_key, free_value); 61 g_hash_table_insert(table, strdup ("one"), strdup("first")); 62 g_hash_table_insert(table, strdup("two"), strdup("second")); 63 g_hash_table_insert(table, strdup("three"), strdup("third")); 64 65 printf("Remove an item from 代码中我们用strdup()来为hash表的key和value动态分配内。
index *= 1103515245 + (int)key[i]; } index >>= 27; index &= (BUCKETCOUNT – 1); return index; } 辅助函数strDup //在堆上分配足以保存str的内存 //并拷贝str内容到新分配位置 char* strDup(const char* str) { int len; char* ret; if (str == NULL NULL) { memcpy(ret , str , len); ret[len] = ‘\0’; } return ret; } string.h中的相关函数 #include char *strdup (key); t->bucket[index].value = strDup(value); } else { e = ep = &(t->bucket[index]); while (e ! (key); e->value = strDup(value); e->next = NULL; ep->next = e; } return index; } 哈希表中查找 因为这个哈希表中保存的是键值对
const char *cgiargs, char uri[8192]) { char buf[MAXLINE], *emptylist[] = {NULL}; char *url=strdup (uri); // 假设有一个 strdup 函数用于字符串 char** argName= malloc(sizeof(char*)*50); char** argValue=malloc argkey=argvalue) char *start = strdup(strchr(uri,' ')); start++; char *end = strchr(start (key); (*argValue)[numParams] = strdup(value); // printf("%s %s\n",(*argName)[ (strcat(strdup(POST_ROUTE_LOGIN),"?
(yytext); return tok_request; } "response" { yylval.sval = strdup(yytext); return tok_response ; } "string" { yylval.sval = strdup(yytext); return tok_string; } "bool" { yylval.sval = strdup(yytext); return tok_bool; } "int16" { yylval.sval = strdup (yytext); return tok_int16; } "int32" { yylval.sval = strdup(yytext); return tok_int32 { yylval.sval = strdup(yytext); return tok_double; } "required" { yylval.sval = strdup
// 有些如STM32就不自带strdup函数 #if ! HAVE_STRDUP #undef strdup char *strdup(const char *s) { size_t len = strlen(s) + 1;//计算字符串的长度 void sizeof(HashNode)); if (node == NULL) { return 0; } // 复制键和值 node->key = strdup (key); node->value = strdup(value); node->next = NULL; // 对hash结果求余,获取key位置 int index value myFree(temp->value); // 复制新value temp->value = strdup
g_printerr ("--user specified twice\n"); goto out; } opt_user = g_strdup opt_disable_internal_agent = TRUE; } else { break; } } 然后在610行,获取PROGRAM参数名称,也就是需要执行的程序 path = g_strdup (argv[n]); // 分析代码,我们可以发现n在此时被使用,g_strdup复制目标字符串,但是如果我们不传递任何参数,g_strdup用于拷贝字符串,如果没有参数传递,这里就产生内存越界读取了 if (path == NULL) { GPtrArray *shell_argv; path = g_strdup (pwstruct.pw_shell); if (! command_line) case below too */ command_line = g_strdup (path); shell_argv = g_ptr_array_new ();
//在堆上分配足以保存str的内存 //并拷贝str内容到新分配位置 char* strDup(const char* str) { int len; char* ret; if '\0'; } return ret; }'; } return ret; } string.h中的相关函数 #include <string.h> char *strdup (key); t->bucket[index].value = strDup(value); } else { e = ep = &(t->bucket[ //没有在当前桶中找到 //创建条目加入 e = (entry*)malloc(sizeof (entry)); e->key = strDup(key) ; e->value = strDup(value); e->next = NULL; ep->next = e; } return index
; exit(1); } *(_QWORD *)(a1 + 24) = strdup((const char *)a1); if ( ! = read_addr - libc.symbols["read"] 在泄露栈地址 # info leak ———— leak stack create("C" * 0x20) # show # 利用strdup "canary = " + hex(canary) 使用house of spirit技术,让buf+0x10的地址写到fastbin头指针 # house of spirit # because strdup libc_base + libc.symbols["__malloc_hook"] # info leak ———— leak stack create("C" * 0x20) # show # 利用strdup canary = u64(p.recv(7).ljust(8, "\x00")) print "canary = " + hex(canary) # house of spirit # because strdup
// 有些如STM32就不自带strdup函数 #if ! HAVE_STRDUP #undef strdup char *strdup(const char *s) { size_t len = strlen(s) + 1;//计算字符串的长度 void sizeof(HashNode)); if (node == NULL) { return 0; } // 复制键和值 node->key = strdup (key); node->value = strdup(value); node->next = NULL; // 对hash结果求余,获取key位置 int index value myFree(temp->value); // 复制新value temp->value = strdup
P* T(char *ch) { if (root == NULL) { root = (P*)malloc(sizeof(P)); root->key = strdup else p = p->rlink; } } P* q = (P*)malloc(sizeof(P)); q->key = strdup P* T(char *ch) { if (root == NULL) { root = (P*)malloc(sizeof(P)); root->key = strdup else p = p->rlink; } } P* q = (P*)malloc(sizeof(P)); q->key = strdup
; char *input = strdup(source); char *token = strsep(&input, delim); while (token ! delim) { vector <std::string> strlist; char *p = const_cast<char*>(str.c_str()); char *input = strdup (p); //strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。 string> strlist; char *saveptr = NULL; char *p = const_cast<char*>(str.c_str()); char *input = strdup (p); //strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。
} eXosip_sdp_negotiation_remove_audio_payloads(); eXosip_sdp_negotiation_add_codec(osip_strdup (“0”), NULL, osip_strdup(“RTP/AVP”), NULL, NULL, NULL, NULL,NULL, osip_strdup(“0 PCMU/8000” )); eXosip_sdp_negotiation_add_codec(osip_strdup(“8”), NULL, osip_strdup(“RTP/AVP”), NULL, NULL , NULL, NULL,NULL, osip_strdup(“8 PCMA/8000”)); /* register callbacks?
其它的一些参数设置 } else { break; } } ...其它的一些判断help和version参数的语句, 不改变n的值 path = g_strdup 这时候我们再回到源码中看一下, 是进入for循环: n=1 n<(guint)argc 判断发现 (n=1 > argc=0) 条件不满足,退出循环 ...执行其它一些不会改变n值的代码 path = g_strdup (argv[n]); 实际执行path = g_strdup(argv[1]) 可以看到, 当我们使用execve函数执行pkexec的时候会导致pkexec内部执行代码:g_strdup(argv 那么我们继续回到程序代码中看看接下来执行那些内容: g_assert (argv[argc] == NULL); path = g_strdup(argv[n]); if(path == NULL) { 执行path=g_strdup(argv[n])越界读取到envp[0] = pwnkit.so:. path = 'pwnkit.so:.' 2. if判断发现首字符并不是`/`然后进入if判断语句中
pixel format failed, err=%d", ret); break; } mFilterOutputs->name = av_strdup mFilterOutputs->pad_idx = 0; mFilterOutputs->next = nullptr; mFilterInputs->name = av_strdup
; } template <typename T> static void DeleteArray(T* array) { delete[] array; } // The normal strdup This version of StrDup // uses new and calls the FatalProcessOutOfMemory handler if // allocation fails . // 复制字符串 char* StrDup(const char* str); // Allocation policy for allocating in the C free store using invalid; } void AllStatic::operator delete(void* p) { UNREACHABLE(); } #endif // 复制字符串 char* StrDup
当然,转换方式还是有的:可以用strdup 或者_strdup函数。 //1-2.const char* to char const char* c_arr_name2 = “Android Lollipop”; char* arr_name2 = _strdup (c_arr_name2); //ISO C++ onformant name char* arr_name2 = strdup(c_arr_name2); //The Posix name