安卓逆向之NDK内存管理

news2024/9/21 18:37:30

一:内存管理

在 JNI 中,内存管理是一个重要的主题,尤其是在处理 Java 和 C++ 之间的对象时。以下是一些关键点和最佳实践,以确保有效的内存管理。

1. 局部引用管理

  • 局部引用:在 JNI 中,调用 Java 方法时会创建局部引用。这些引用在方法返回后会被自动释放,但在长时间运行的本地方法中,可能会导致局部引用表溢出。
  • 手动删除:使用 DeleteLocalRef 手动删除不再需要的局部引用。
jobject localRef = env->NewObject(...);
// 使用 localRef
env->DeleteLocalRef(localRef); // 手动删除

2. 全局引用

  • 全局引用:如果需要在多个 JNI 调用之间共享对象,可以创建全局引用。全局引用在整个应用程序生命周期内有效,直到显式删除。
  • 创建全局引用:使用 NewGlobalRef 创建全局引用。
  • 删除全局引用:使用 DeleteGlobalRef 删除全局引用。
jobject globalRef = env->NewGlobalRef(localRef);
// 使用 globalRef
env->DeleteGlobalRef(globalRef); // 手动删除

3. 字符串和数组管理

  • 字符串:使用 GetStringUTFChars 获取 C 字符串时,确保在使用后调用 ReleaseStringUTFChars 释放。
jstring jstr = ...;
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
// 使用 cstr
env->ReleaseStringUTFChars(jstr, cstr); // 释放

  • 数组:在处理 Java 数组时,使用 Get<PrimitiveType>ArrayElements 获取元素,并在使用后调用相应的释放函数。
jintArray intArray = ...;
jint *elements = env->GetIntArrayElements(intArray, nullptr);
// 使用 elements
env->ReleaseIntArrayElements(intArray, elements, 0); // 释放

4. 避免内存泄漏

  • 检查返回值:在调用 JNI 函数时,检查返回值是否为 nullptr,以避免对空指针的操作。
  • 适时释放:确保在不再需要对象时及时释放引用,避免内存泄漏。

5. 使用 CallNonvirtualVoidMethod

当需要调用父类的方法时,可以使用 CallNonvirtualVoidMethod。以下是如何使用它的示例:

示例代码

假设有一个 Java 类 Parent 和一个子类 Child,我们希望从 C++ 中调用 Parent 的方法。

// Parent.java
package com.example.yourapp;

public class Parent {
    public void greet() {
        System.out.println("Hello from Parent!");
    }
}

// Child.java
package com.example.yourapp;

public class Child extends Parent {
    public void greet() {
        System.out.println("Hello from Child!");
    }
}

C++ 代码

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "NativeExample"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_callParentGreet(JNIEnv *env, jobject childObj) {
    // 获取 Parent 类的引用
    jclass parentClass = env->FindClass("com/example/yourapp/Parent");
    if (parentClass == nullptr) {
        LOGI("Failed to find Parent class");
        return;
    }

    // 获取 greet 方法的 ID
    jmethodID greetMethod = env->GetMethodID(parentClass, "greet", "()V");
    if (greetMethod == nullptr) {
        LOGI("Failed to find greet method");
        return;
    }

    // 调用 Parent 的 greet 方法
    env->CallNonvirtualVoidMethod(childObj, parentClass, greetMethod);

    // 释放局部引用
    env->DeleteLocalRef(parentClass);
}

代码解释

  1. 获取类引用:使用 FindClass 获取父类 Parent 的引用。
  2. 获取方法 ID:使用 GetMethodID 获取 greet 方法的 ID。
  3. 调用父类方法:使用 CallNonvirtualVoidMethod 调用父类的 greet 方法。
  4. 释放局部引用:确保释放所有局部引用以避免内存泄漏。

1.局部引用

大多数的jni函数,调用以后返回的结果都是局部引用

因此env→NewLocalRef基本不用

一个函数内的局部引用数量是有限的,在早期的安卓系统中,体现的更未明显,当函数内需要大量局部引用时,比如大循环中,最好及时删除不用的局部引用,可以使用env→DeleLocalRef来删除局部引用.

局部引用是 JNI 中的重要概念,它们用于管理从 Java 代码中创建的对象的生命周期。理解局部引用的工作原理对于确保在 JNI 中有效的内存管理至关重要。

什么是局部引用?

局部引用是在 JNI 方法中创建的对象引用,这些引用在方法执行期间有效。当 JNI 方法返回时,这些局部引用会被自动释放。局部引用的作用范围仅限于创建它们的 JNI 方法。

创建局部引用

局部引用通常通过 JNI 函数创建,例如:

  • NewObject:创建一个新的 Java 对象。
  • NewStringUTF:创建一个新的字符串对象。
  • GetObjectArrayElement:从对象数组中获取元素。

示例

jclass myClass = env->FindClass("com/example/MyClass");
jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");
jobject myObject = env->NewObject(myClass, constructor);

在这个例子中,myObject 是一个局部引用,指向新创建的 Java 对象。

管理局部引用

虽然局部引用在方法返回时会被自动释放,但在某些情况下(例如长时间运行的本地方法),可能会导致局部引用表溢出。因此,适当管理局部引用非常重要。

1. 手动删除局部引用

在不再需要某个局部引用时,可以使用 DeleteLocalRef 手动删除它,以释放内存:

env->DeleteLocalRef(myObject);

2. 避免局部引用溢出

如果在一个 JNI 方法中创建了大量的局部引用,可能会导致局部引用表溢出。可以使用以下方法来避免这种情况:

  • 定期删除局部引用:在循环中创建局部引用时,定期调用 DeleteLocalRef
  • 使用 PushLocalFramePopLocalFrame:这两个方法允许你在局部引用帧中管理局部引用的生命周期。
env->PushLocalFrame(16); // 创建一个局部引用帧,最多可以存储 16 个局部引用
jobject localRef = env->NewObject(...);
// 使用 localRef
env->PopLocalFrame(nullptr); // 释放局部引用帧中的所有引用

例子:局部引用的使用

以下是一个简单的例子,展示如何在 JNI 中使用局部引用:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {
    jclass stringClass = env->FindClass("java/lang/String");
    if (stringClass == nullptr) {
        return; // 处理错误
    }

    jmethodID constructor = env->GetMethodID(stringClass, "<init>", "(Ljava/lang/String;)V");
    jstring jstr = env->NewStringUTF("Hello from JNI!");

    jobject myStringObject = env->NewObject(stringClass, constructor, jstr);

    // 使用 myStringObject
    // ...

    // 释放局部引用
    env->DeleteLocalRef(jstr);
    env->DeleteLocalRef(myStringObject);
    env->DeleteLocalRef(stringClass);
}

总结

局部引用是 JNI 中管理 Java 对象的基本机制。正确使用和管理局部引用可以避免内存泄漏和局部引用表溢出。通过手动删除不再需要的引用和使用局部引用帧,可以有效地控制内存使用。

2.局部引用相关的其他函数

env→EnsureLocalcapacity(num),判断是否有足够的局部引用可以使用,足够则返回0,需要大量使用局部引用时,手动删除太麻烦,可以使用一下俩个函数来批量管理局部引用.

env→PushLocalFrame(num)

env→PopLocalFrame(nullptr)

在 JNI 中,除了基本的局部引用管理函数 NewLocalRefDeleteLocalRef 外,还有一些其他相关的函数,可以帮助管理和优化局部引用的使用。以下是一些重要的局部引用相关函数及其用途:

1. PushLocalFramePopLocalFrame

  • PushLocalFrame:创建一个新的局部引用帧,可以在该帧中存储局部引用。局部引用将在帧被弹出时自动释放。
  • PopLocalFrame:释放局部引用帧中的所有局部引用。

示例

env->PushLocalFrame(10); // 创建一个局部引用帧,最多可以存储 10 个局部引用

jobject localRef1 = env->NewObject(...);
jobject localRef2 = env->NewObject(...);
// 使用 localRef1 和 localRef2

env->PopLocalFrame(nullptr); // 释放局部引用帧中的所有引用

2. NewLocalRef

  • NewLocalRef:创建一个新的局部引用,指向现有的对象。它可以用于将全局引用或其他局部引用转换为局部引用。

示例

jobject globalRef = env->NewGlobalRef(someObject);
jobject localRef = env->NewLocalRef(globalRef); // 将全局引用转换为局部引用
// 使用 localRef
env->DeleteLocalRef(localRef);
env->DeleteGlobalRef(globalRef); // 释放全局引用

3. GetObjectArrayElement

  • GetObjectArrayElement:从 Java 对象数组中获取元素,返回的对象是局部引用。

示例

jobjectArray objectArray = ...; // 假设这是一个有效的 jobjectArray
jobject element = env->GetObjectArrayElement(objectArray, index);
// 使用 element
env->DeleteLocalRef(element); // 释放局部引用

4. SetObjectArrayElement

  • SetObjectArrayElement:将一个对象设置到 Java 对象数组中的指定索引。传入的对象可以是局部引用。

示例

jobjectArray objectArray = ...; // 假设这是一个有效的 jobjectArray
jobject newElement = env->NewObject(...); // 创建一个新的对象
env->SetObjectArrayElement(objectArray, index, newElement);
env->DeleteLocalRef(newElement); // 释放局部引用

5. CallObjectMethod

  • CallObjectMethod:调用对象的方法并返回一个对象,返回的对象是局部引用。

示例

jobject result = env->CallObjectMethod(someObject, methodID);
// 使用 result
env->DeleteLocalRef(result); // 释放局部引用

6. GetMethodIDGetFieldID

  • GetMethodIDGetFieldID:虽然这些函数本身不创建局部引用,但它们返回的方法和字段 ID 可以用于后续操作,调用这些方法或访问字段时会产生局部引用。

示例

jclass clazz = env->FindClass("com/example/MyClass");
jmethodID methodID = env->GetMethodID(clazz, "myMethod", "()V");
jfieldID fieldID = env->GetFieldID(clazz, "myField", "Ljava/lang/String;");

7. GetStringUTFCharsReleaseStringUTFChars

  • GetStringUTFChars:获取 Java 字符串的 C 字符串表示,返回的指针需要在使用后释放。
  • ReleaseStringUTFChars:释放通过 GetStringUTFChars 获取的 C 字符串。

示例

jstring jstr = ...;
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
// 使用 cstr
env->ReleaseStringUTFChars(jstr, cstr); // 释放

3.全局引用


在 JNI 中,全局引用是一种特殊的引用类型,用于在 C++ 代码中持有 Java 对象的引用。与局部引用不同,全局引用在 JNI 方法返回后仍然有效,直到显式删除。全局引用的主要用途是允许跨多个 JNI 方法或线程使用 Java 对象。

什么是全局引用?

全局引用是在 JNI 中创建的对象引用,可以在整个应用程序生命周期内使用。它们的主要特性包括:

  • 持久性:全局引用在创建后不会自动释放,直到调用 DeleteGlobalRef 显式删除。
  • 跨方法和线程:全局引用可以在不同的 JNI 方法和线程之间共享。

创建全局引用

要创建全局引用,可以使用 NewGlobalRef 函数。以下是创建全局引用的示例:

jobject localRef = env->NewObject(...); // 创建一个局部引用
jobject globalRef = env->NewGlobalRef(localRef); // 创建全局引用
env->DeleteLocalRef(localRef); // 可以安全地删除局部引用

删除全局引用

全局引用在不再需要时必须显式删除,以避免内存泄漏。使用 DeleteGlobalRef 来删除全局引用:

env->DeleteGlobalRef(globalRef); // 删除全局引用

使用全局引用

全局引用可以在 JNI 方法中安全地使用,以下是一个使用全局引用的示例:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_useGlobalRef(JNIEnv *env, jobject obj) {
    // 创建一个局部引用并转换为全局引用
    jclass myClass = env->FindClass("com/example/MyClass");
    jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");
    jobject localRef = env->NewObject(myClass, constructor);
    jobject globalRef = env->NewGlobalRef(localRef);
    env->DeleteLocalRef(localRef); // 删除局部引用

    // 使用全局引用
    jmethodID someMethod = env->GetMethodID(myClass, "someMethod", "()V");
    env->CallVoidMethod(globalRef, someMethod);

    // 删除全局引用
    env->DeleteGlobalRef(globalRef);
}

全局引用的注意事项

  1. 内存管理:全局引用不会自动释放,因此必须在不再需要时手动删除,以避免内存泄漏。
  2. 线程安全:全局引用可以在多个线程中使用,但需要确保在多线程环境中对全局引用的访问是线程安全的。
  3. 局部引用与全局引用的选择:如果只需在单个 JNI 方法中使用对象,使用局部引用即可。如果需要在多个方法或线程之间共享对象,则应使用全局引用。

例子:全局引用管理

以下是一个完整的示例,展示如何在 JNI 中创建和使用全局引用:

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "NativeExample"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {
    // 创建一个局部引用
    jclass myClass = env->FindClass("com/example/MyClass");
    jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");
    jobject localRef = env->NewObject(myClass, constructor);

    // 创建全局引用
    jobject globalRef = env->NewGlobalRef(localRef);
    env->DeleteLocalRef(localRef); // 删除局部引用

    // 调用方法
    jmethodID someMethod = env->GetMethodID(myClass, "someMethod", "()V");
    env->CallVoidMethod(globalRef, someMethod);

    // 删除全局引用
    env->DeleteGlobalRef(globalRef);
}

总结

全局引用在 JNI 中提供了一种持久的方式来管理 Java 对象,允许跨多个 JNI 方法和线程使用这些对象。正确管理全局引用至关重要,以避免内存泄漏和确保应用程序的稳定性。通过适当的创建和删除全局引用,可以有效地在 C++ 和 Java 之间进行交互。

4.弱全局引用

在 JNI 中,全局引用和弱全局引用是用于管理 Java 对象生命周期的两种重要引用类型。它们在内存管理、性能优化和避免内存泄漏方面具有不同的特性和使用场景。

全局引用

全局引用是 JNI 中一种特殊的引用类型,它可以在多个 JNI 调用之间共享,并在整个应用程序生命周期内有效。全局引用不会被垃圾回收器自动释放,直到显式删除。

创建全局引用

使用 NewGlobalRef 创建全局引用:

jobject globalRef = env->NewGlobalRef(localRef);

删除全局引用

使用 DeleteGlobalRef 删除全局引用:

env->DeleteGlobalRef(globalRef);

弱全局引用

弱全局引用(Weak Global Reference)是一种特殊的引用类型,它允许程序在不阻止对象被垃圾回收的情况下引用 Java 对象。弱全局引用在 Java 中的生命周期与普通全局引用不同,垃圾回收器可以在需要时回收弱全局引用指向的对象。

创建弱全局引用

使用 NewWeakGlobalRef 创建弱全局引用:

jobject weakGlobalRef = env->NewWeakGlobalRef(localRef);

删除弱全局引用

使用 DeleteWeakGlobalRef 删除弱全局引用:

env->DeleteWeakGlobalRef(weakGlobalRef);

使用弱全局引用的场景

  1. 避免内存泄漏:在某些情况下,使用弱全局引用可以防止强引用导致的内存泄漏。例如,当你想要缓存对象,但又不希望阻止它们被垃圾回收时,可以使用弱全局引用。
  2. 缓存对象:在某些情况下,可以使用弱全局引用缓存对象,以便在需要时访问,但不阻止对象被回收。
  3. 事件处理:在事件处理或回调机制中,使用弱全局引用可以避免循环引用的问题。

检查弱全局引用的有效性

由于弱全局引用在对象被垃圾回收后会变为 nullptr,因此在使用弱全局引用之前,应该检查它是否仍然有效。可以使用 IsSameObject 来检查弱全局引用是否指向一个有效的对象。

示例代码

以下是一个使用弱全局引用的示例:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {
    // 创建一个局部引用
    jobject localRef = env->NewObject(...);

    // 创建弱全局引用
    jobject weakGlobalRef = env->NewWeakGlobalRef(localRef);

    // 删除局部引用
    env->DeleteLocalRef(localRef);

    // 检查弱全局引用是否有效
    if (weakGlobalRef != nullptr) {
        // 使用 weakGlobalRef
        // ...
    } else {
        // 对象已被垃圾回收
    }

    // 删除弱全局引用
    env->DeleteWeakGlobalRef(weakGlobalRef);
}

总结

弱全局引用在 JNI 中提供了一种灵活的方式来管理 Java 对象的生命周期。它们允许程序在不阻止对象被垃圾回收的情况下引用对象,从而帮助避免内存泄漏和循环引用。使用弱全局引用时,确保在使用之前检查其有效性,以避免访问已被回收的对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153021.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【java实现json转化为CSV文件】

文章目录 JSON文件中的数据格式测试文件转换的接口 JSON文件中的数据格式 单条数据展开后如下&#xff1a; {"text": "《邪少兵王》是冰火未央写的网络小说连载于旗峰天下","spo_list":[{"predicate": "作者", "objec…

Windows环境下搭建MySQL主从同步实现读写分离

文章目录 前言读写分离的基本原理 环境介绍及说明主库my.ini初始配置创建用于同步的数据库和表 一、新增mysql从库1.复制mysql文件夹2.修改从库的my.ini3.安装到windows服务 二、在my.ini中配置主、从库相关参数1.主库新增配置参数不同版本参数不同问题 2.从库新增配置参数3.删…

rabbitmq 短信验证码

1.生成的验证码用redis存 减少数据库压力 2.通知运营商发送短信的事情交给rabbitmq的队列去做&#xff0c;无论成功或者是失败&#xff0c;用户那边都不知道。没有收到验证码&#xff08;监听失败&#xff09;用户只会觉得是运营商的问题&#xff0c;而不会怀疑是我们的系统有问…

Linux文件IO(四)-返回错误处理与errno详解

1.前言 在上一文章中&#xff0c;给大家编写了很多的示例代码&#xff0c;大家会发现这些示例代码会有一个共同的特点&#xff0c;那就是当判断函数执行失败后&#xff0c;会调用 return 退出程序&#xff0c;但是对于我们来说&#xff0c;我们并不知道为什么会出错&#xff0…

C++进阶|多态知识点详解及经典面试题总结

&#x1f36c; mooridy-CSDN博客 &#x1f9c1;C专栏&#xff08;更新中&#xff01;&#xff09; 目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.2 虚函数的重写/覆盖 2.3 虚函数重写的⼀些其他问题 2.4 override 和 final关键字 2.5 重载/重写/隐藏的…

(笔记自用)位运算总结+LeetCode例题:颠倒二进制位+位1的个数

一.位运算总结: 在解题之前理解一下为什么需要位运算&#xff1f;它的本质是什么&#xff1f; 力扣上不少位运算相关的题&#xff0c;并且很多题也会用到位运算的技巧。这又是为什么&#xff1f; 位运算的由来 在计算机里面&#xff0c;任何数据最终都是用数字来表示的&…

mysqldump使用cmd窗口和powersell窗口导出sql中文乱码的问题

项目场景 我在使用Mariadb数据库更新数据的时候&#xff0c;由于数据库的表格中含有中文&#xff0c;在使用mysqldump导出sql语句的时候&#xff0c;中文显示乱码&#xff0c;如下图所示&#xff1a; 环境描述 系统&#xff1a;windows10数据库&#xff1a; Mariadb -10.6.16…

Vue2中路由的介绍和使用

一.路由的基本概念 一说路由&#xff0c;大家首先想到的可能是路由器&#xff0c;路由器的原理就是给连接的设备一个IP地址&#xff0c;通过IP地址来映射到设备&#xff0c;实现连接&#xff0c;本质上是一种映射关系。 在vue2中就是路径与组件间的映射。 路由是使用vue2制作…

Python爬虫使用实例-umei

优美图库 www.umei.cc BV1Ag41137re 1/获取资源 查看网站资源结构 多页&#xff0c;每个item只有一张图 多页&#xff0c;每个item都是一个图集 最大页码 内外层图集均有若干page。 通过尾页按钮确定pageNum&#xff1a; 2/发送请求 response requests.get(urlurl, header…

快速将Mongo Compass的shell语句转成java代码

步骤一、从MongoCompass中获取java代码 将java代码复制出来&#xff0c;从MongoCompass中复制的java代码基本格式如下&#xff1a;&#xff08;是Bson原生格式&#xff09; List<Document> list Arrays.asList(new Document("$match",new Document("name…

探索视频美颜SDK与直播美颜工具的开发实践方案

直播平台的不断发展&#xff0c;让开发出性能优异、效果自然的美颜技术&#xff0c;成为了技术团队必须面对的重要挑战。本篇文章&#xff0c;小编将深入讲解视频美颜SDK与直播美颜工具的开发实践方案。 一、视频美颜SDK的核心功能 视频美颜SDK是视频处理中的核心组件&#xf…

Cocos Creator3.x设置动态加载背景图并且循环移动

效果图 项目结构 项目层级结构&#xff1a; 预制&#xff1a; 代码 import { _decorator, CCFloat, Component, Node, Sprite, instantiate, Prefab, assert } from cc; const { ccclass, property } _decorator;/*** 背景脚本*/ ccclass(Background) export class Backg…

2024年华为杯研赛(D题)数学建模竞赛解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…

反激电路中TL431光耦反馈参数的计算,环路设计思路

反馈的过程 当副边的输出电压升高时&#xff0c;TL431参考端电压&#xff08;R端&#xff09;电压也会升高&#xff0c;使得TL431的导通量增加&#xff0c;同时光耦内部的发光二极管流过的电流也会增大&#xff0c;进而使得光耦三极管导通量增加&#xff0c;相连的电源IC电压反…

《粮油与饲料科技》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《粮油与饲料科技》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定 学术期刊。 问&#xff1a;《粮油与饲料科技》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;中文天地出版传媒集团股份有限公司…

缺陷及缺陷管理(复习)

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 今日目标 能够说出缺陷的判定标准 能够说出描述缺陷的6大核心内容 能够描述缺陷状态、严重程度、优先级的作用 能够按照提供的缺陷模版完成一个缺陷的提交 能够说出缺陷的跟踪流程 能够在禅道中提交测…

黑神话:悟空配置推荐,升级显卡还是ToDesk云电脑

虽然距离《黑神话&#xff1a;悟空》上线已有一个月的时间&#xff0c;但该游戏在国内外市场仍然火热&#xff0c;想要玩好、玩顺它着实是需要花费一些心力的。除了操作上的经验、技巧&#xff0c;用高配置电脑设备来实现无疑是最为关键的要素之一。那么如若现有机型性能不足&a…

2024年华为杯数学建模研赛(C题) 建模解析| 磁芯损耗建模 | 小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮2000人完成了建模与思路的构建的处理了&#xff5e; 本篇文章是鹿鹿学长经过深度思考&#xff0c;独辟蹊径&#xff0c;实现综合建模。独创复杂系统视角&#xff0c;帮助你解决研赛的难关呀。 完整内容可…

(学习总结18)C++多态

C多态 一、多态的概念二、多态的定义及实现多态的构成条件1. 实现多态的两个必须条件&#xff1a;2. 虚函数3. 虚函数的重写/覆盖4. 多态场景的一个选择题5. 虚函数重写的一些其他问题协变析构函数的重写 6. override 和 final 关键字7. 重载/重写/隐藏的对比 三、纯虚函数和抽…

【堆栈操作基本规则】假设SS的初值为2000H,SP初值为0200H,在执行了5次入栈操作和2次出栈操作后SP的内容为多少?写出计算过程。

欢迎来到我的技术博客&#xff01; &#x1f389; 这里不仅有满满的编程干货和学习资源&#xff0c;我的某站账号也为你准备了更多实用的技术视频和知识分享。 &#x1f449; 点击关注我的小破站账号&#xff0c;获取更多编程技巧和学习资源&#xff01; 小破站主页 我们来逐…