malloc的问题,太诡异了
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void upcase(char *oldstr, char *newstr);
int main(void)
{
char *string = NULL;
upcase("Hello", string);
printf("str1=%s \n", string);
free(string);
upcase("Goodbye", string);
printf("str2=%s\n", string);
free(string);
return 0;
}
void upcase(char *oldstr, char *newstr)
{
int i;
newstr = malloc(strlen(oldstr) + 1);
strcpy(newstr, oldstr);
printf("%s\n",newstr);
for (i = 0; i < strlen(newstr); i++)
{
newstr[i] = toupper(newstr[i]);
}
return;
}
执行结果是:
Hello
str1=(null)
Goodbye
str2=(null)
为什么是这样子?
相关推荐
一次malloc失败,彻底搞懂Linux内存管理全链路
内存管理是操作系统绕不开的核心课题。进程通过虚拟地址空间访问物理内存,页表与缺页异常机制实现了按需分配,而malloc作为用户态内存入口,其底层依赖glibc的堆管理、内核的伙伴系统与slab分配器,并受到overcommit、cgroup等因素影响。理解这条链路,能够帮助开发者快速定位“内存看似充足却分配失败”等问题。在容器化服务、C/C++后端及高并发场景中,内存瓶颈常表现为malloc失败或OOM,掌握free、/proc/pid/smaps等排查工具尤为关键。本文从一个真实线上malloc失败案例出
深入剖析malloc重入陷阱:从__lll_lock_wait_private看线程安全与死锁防范
本文深入剖析了malloc在多线程环境下因信号中断导致的重入死锁问题。通过分析__lll_lock_wait_private调用栈,揭示了glibc内存分配器线程安全但不可重入的特性,并提供了信号处理函数安全编程准则与多线程环境下的规避策略,帮助开发者防范此类隐蔽死锁。
C/C++内存分配:malloc与new的核心区别与实战选用指南
内存管理是编程中的基础概念,它决定了程序如何高效、安全地使用系统资源。其核心原理在于程序运行时向操作系统动态申请和释放内存空间,以满足数据结构与对象的存储需求。这一机制的技术价值在于,它使程序能够灵活处理未知或变化的数据规模,是构建复杂软件系统的基石,广泛应用于操作系统、游戏引擎、数据库及高性能计算等场景。在C/C++领域,内存分配主要通过malloc/free和new/delete两套机制实现,它们分别代表了C语言的原始内存操作与C++面向对象的一站式服务。理解其底层差异,对于避免内存泄漏、野指针等关键问
C++内存管理:new/delete与malloc/free核心差异与实战指南
内存管理是编程语言的核心基础,它决定了程序如何高效、安全地使用系统资源。在C++中,动态内存分配涉及两个关键概念:C语言风格的malloc/free函数和C++特有的new/delete操作符。从原理上看,malloc/free是纯粹的内存分配器,只负责原始内存块的申请与释放;而new/delete则是对象生命周期管理器,在分配内存的同时自动调用构造函数和析构函数,实现了C++的RAII(资源获取即初始化)核心机制。这种设计差异带来了类型安全、异常处理、与面向对象特性深度协同等技术价值,使得new/dele
C语言数组与malloc初始化:静态与动态内存管理核心差异详解
在C语言编程中,内存初始化是确保程序稳定性和性能的基础。从概念上讲,初始化是为变量或内存区域赋予初始值的过程,其原理根据存储类型分为编译时初始化和运行时初始化。静态存储期变量(如全局数组)在程序加载时由系统自动清零,而自动存储期变量(如局部数组)则包含未定义的垃圾值,这直接关系到程序的安全性与可预测性。动态内存分配通过malloc、calloc等函数在堆上运行时申请内存,但分配的内存内容未定义,需要程序员手动初始化,这体现了C语言对内存的精细控制权与技术价值。在应用场景上,数组适用于大小固定、生命周期明确的


