BlogTổng hợp các Method/Hàm chuyên dụng, phổ biến trong C/C++
Bố cục bài viết
Trang này
Ngày tạo
13/08/2026
Cập nhật
Lượt xem
5
Đọc
21m
Tổng hợp các Method/Hàm chuyên dụng, phổ biến trong C/C++
Tài liệu liệt kê các hàm/method thường gặp nhất khi lập trình C/C++, kèm giải thích công dụng, ví dụ dùng, và lưu ý an toàn (đặc biệt quan trọng khi làm embedded/viễn thông/an ninh mạng — xem thêm file
nguyen-tac-lap-trinh-C-CPP.md).Ký hiệu: 🔴 = nguy hiểm/nên tránh hoặc cần cẩn trọng đặc biệt · 🟢 = khuyến nghị dùng thay thế.
Mục lục
- Quản lý bộ nhớ
- Chuỗi ký tự (String)
- Con trỏ thông minh (Smart Pointer) — C++
- STL Container phổ biến
- STL Algorithm phổ biến
- Move semantics & Perfect forwarding
- Vào/Ra dữ liệu (I/O)
- Đa luồng (Concurrency)
- Xử lý số & Bit
- Mạng, Byte order & Serialize
- Bảo mật / Crypto
- Kiểm tra lúc biên dịch & Debug
- Bảng tra nhanh: “Đừng dùng cái này — dùng cái kia”
1. Quản lý bộ nhớ
| Hàm/Method | Header | Công dụng |
|---|---|---|
malloc(size_t) | <cstdlib> | Cấp phát vùng nhớ thô size byte, không khởi tạo giá trị, trả về void* (cần cast trong C++). Trả NULL nếu thất bại — luôn phải kiểm tra. |
calloc(n, size) | <cstdlib> | Giống malloc nhưng cấp phát cho n phần tử và tự động khởi tạo về 0. An toàn hơn malloc khi cần buffer sạch. |
realloc(ptr, size) | <cstdlib> | Thay đổi kích thước vùng nhớ đã cấp phát. 🔴 Lưu ý: nếu thất bại trả NULL nhưng con trỏ cũ vẫn còn — không gán đè trực tiếp ptr = realloc(ptr, ...) vì sẽ leak nếu thất bại. |
free(ptr) | <cstdlib> | Giải phóng vùng nhớ do malloc/calloc/realloc cấp. 🔴 Gọi free hai lần (double-free) hoặc dùng con trỏ sau khi free (use-after-free) là UB nghiêm trọng, thường bị khai thác bảo mật. |
new / new[] | (từ khóa) | Cấp phát bộ nhớ và gọi constructor. Ném std::bad_alloc nếu thất bại (khác malloc trả NULL). |
delete / delete[] | (từ khóa) | Gọi destructor và giải phóng bộ nhớ. 🔴 Phải khớp: new đi với delete, new[] đi với delete[] — lẫn lộn là UB. |
new(std::nothrow) | <new> | Biến thể của new không ném exception mà trả nullptr khi thất bại — dùng khi code không cho phép exception (embedded). |
std::make_unique<T>(args...) 🟢 | <memory> | Cách khuyến nghị để tạo unique_ptr — an toàn hơn new trần vì tránh leak khi có exception giữa new và gán vào smart pointer. |
std::make_shared<T>(args...) 🟢 | <memory> | Tương tự cho shared_ptr, đồng thời tối ưu hơn (gộp một lần cấp phát cho object + control block thay vì hai lần). |
std::allocator<T> | <memory> | Bộ cấp phát bộ nhớ chuẩn hóa dùng bên trong container STL — dùng khi viết container tùy chỉnh hoặc cần custom allocator (phổ biến trong embedded để dùng memory pool). |
placement new — new(ptr) T(args) | <new> | Gọi constructor tại một vùng nhớ đã cấp phát sẵn (không cấp phát mới). Dùng nhiều trong embedded/memory pool khi cần kiểm soát chính xác vị trí object trong bộ nhớ. |
memcpy(dst, src, n) | <cstring> | Sao chép n byte từ src sang dst. 🔴 Vùng nhớ không được chồng lấn (overlap) — nếu chồng lấn phải dùng memmove. |
memmove(dst, src, n) 🟢 | <cstring> | Giống memcpy nhưng an toàn khi vùng nhớ nguồn/đích chồng lấn nhau. |
memset(ptr, value, n) | <cstring> | Gán n byte tại ptr bằng giá trị value (thường dùng để zero-hóa buffer). 🔴 Không dùng để xóa dữ liệu bí mật — compiler có thể tối ưu bỏ qua nếu biến không được đọc lại sau đó (dùng explicit_bzero/memset_s thay thế). |
memcmp(a, b, n) | <cstring> | So sánh n byte đầu của hai vùng nhớ. 🔴 Không dùng để so sánh dữ liệu bảo mật (mật khẩu, MAC, token) vì dừng sớm khi gặp byte khác → lộ thông tin qua thời gian xử lý (timing attack). Dùng hàm constant-time thay thế (xem Mục 11). |
// Ví dụ đúng cách dùng realloc an toàn
void* new_ptr = realloc(old_ptr, new_size);
if (new_ptr == NULL) {
// xử lý lỗi, old_ptr vẫn còn hợp lệ, có thể free nó
free(old_ptr);
return -1;
}
old_ptr = new_ptr; // chỉ gán khi chắc chắn thành công
2. Chuỗi ký tự (String)
2.1. Hàm C-style (từ <cstring>) — cẩn trọng cao độ
| Hàm | Công dụng | Mức độ an toàn |
|---|---|---|
strcpy(dst, src) | Sao chép chuỗi | 🔴 Cấm dùng — không kiểm tra biên, nguyên nhân kinh điển của buffer overflow |
strcat(dst, src) | Nối chuỗi | 🔴 Cấm dùng — cùng lý do trên |
sprintf(buf, fmt, ...) | Format chuỗi vào buffer | 🔴 Cấm dùng — không giới hạn kích thước ghi |
gets(buf) | Đọc dòng từ input | 🔴 Đã bị loại bỏ khỏi chuẩn C11 — tuyệt đối không dùng |
strncpy(dst, src, n) | Sao chép tối đa n ký tự | ⚠️ An toàn hơn nhưng không tự động thêm \0 nếu src dài hơn n — dễ gây lỗi nếu quên tự thêm |
snprintf(buf, size, fmt, ...) 🟢 | Format chuỗi có giới hạn kích thước | An toàn — luôn dùng thay cho sprintf |
strlen(s) | Đếm độ dài chuỗi (không tính \0) | An toàn nếu chuỗi đã kết thúc đúng bằng \0; 🔴 nếu buffer không có \0 sẽ đọc tràn ngoài biên |
strncat(dst, src, n) | Nối tối đa n ký tự | An toàn hơn strcat nhưng vẫn dễ nhầm kích thước buffer đích |
strtol/strtoul/strtod | Chuyển chuỗi sang số nguyên/thực | An toàn hơn atoi/atof vì có báo lỗi qua con trỏ endptr |
atoi/atof | Chuyển chuỗi sang số | ⚠️ Không báo lỗi khi chuỗi không hợp lệ (trả về 0) — không nên dùng khi cần validate input |
2.2. C++ String — khuyến nghị dùng thay thế
| Method | Công dụng |
|---|---|
std::string 🟢 | Chuỗi tự quản lý bộ nhớ, tự động resize, an toàn hơn C-string rất nhiều. Nên dùng mặc định trừ khi có lý do đặc biệt (embedded hạn chế heap). |
.substr(pos, len) | Lấy chuỗi con |
.find(str) | Tìm vị trí xuất hiện, trả std::string::npos nếu không tìm thấy |
.append() / operator+= | Nối chuỗi, tự quản lý bộ nhớ |
.c_str() | Lấy con trỏ C-string (const char*) để tương tác với API C |
std::string_view 🟢 (C++17) | “Nhìn” vào một chuỗi đã tồn tại không copy dữ liệu — cực kỳ hiệu quả khi chỉ cần đọc, không cần sở hữu chuỗi. 🔴 Không giữ string_view lâu hơn vòng đời chuỗi gốc (dangling). |
std::to_string(n) | Chuyển số sang std::string |
std::stoi/stol/stod | Chuyển chuỗi sang số, ném exception nếu không hợp lệ (khác atoi) |
// Không tốt
char buf[64];
sprintf(buf, "value=%d", x); // có thể tràn nếu format string dài
// Tốt
char buf[64];
snprintf(buf, sizeof(buf), "value=%d", x); // luôn an toàn, tự cắt bớt nếu quá dài
// C++ hiện đại
std::string s = "value=" + std::to_string(x);
3. Con trỏ thông minh (Smart Pointer) — C++
| Method | Công dụng |
|---|---|
std::unique_ptr<T> | Sở hữu duy nhất một object, tự giải phóng khi ra khỏi scope. Không copy được, chỉ move (std::move). Chi phí runtime gần như bằng 0 so với con trỏ thô. |
.get() | Lấy con trỏ thô bên trong (để tương tác API cũ) — không tự ý delete nó, quyền sở hữu vẫn thuộc unique_ptr. |
.release() | Trả quyền sở hữu con trỏ ra ngoài, unique_ptr không còn quản lý nó nữa (người gọi phải tự delete sau này). |
.reset(ptr) | Giải phóng object hiện tại (nếu có) và nhận quản lý object mới. |
std::shared_ptr<T> | Nhiều nơi cùng sở hữu một object, tự đếm tham chiếu (reference counting), giải phóng khi tham chiếu cuối cùng biến mất. Chi phí cao hơn unique_ptr (atomic increment/decrement). |
.use_count() | Số lượng shared_ptr đang cùng trỏ tới object — hữu ích khi debug leak. |
std::weak_ptr<T> | “Quan sát” một shared_ptr mà không tăng reference count — dùng để phá vòng lặp tham chiếu (circular reference) giữa hai shared_ptr trỏ lẫn nhau, tránh leak. |
.lock() | Từ weak_ptr, thử lấy shared_ptr hợp lệ — trả về rỗng nếu object đã bị hủy. |
std::enable_shared_from_this<T> | Cho phép một object tự tạo shared_ptr trỏ đến chính nó một cách an toàn (dùng trong callback/async). |
// Ví dụ vòng lặp tham chiếu — cần weak_ptr để tránh leak
struct Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // dùng weak_ptr để phá vòng lặp
};
4. STL Container phổ biến
| Container | Đặc điểm | Khi nào dùng |
|---|---|---|
std::vector<T> | Mảng động, liên tục trong bộ nhớ (cache-friendly) | Mặc định nên dùng khi cần danh sách có thứ tự |
std::array<T, N> | Mảng kích thước cố định biết trước lúc compile | Embedded/real-time — không cấp phát động |
std::deque<T> | Mảng động hai đầu, thêm/xóa đầu-cuối nhanh | Khi cần push/pop cả hai đầu |
std::list<T> | Danh sách liên kết đôi | Khi cần chèn/xóa giữa danh sách thường xuyên, không cần truy cập ngẫu nhiên |
std::map<K,V> | Cây nhị phân cân bằng (thường Red-Black tree), tự sắp xếp theo key | Khi cần key có thứ tự, độ phức tạp O(log n) |
std::unordered_map<K,V> | Bảng băm (hash table) | Khi cần tra cứu nhanh O(1) trung bình, không cần thứ tự |
std::set<T> / std::unordered_set<T> | Tương tự map nhưng chỉ lưu key (không value) | Khi cần tập hợp không trùng lặp |
std::span<T> (C++20) 🟢 | “Nhìn” vào một mảng/vùng nhớ liên tục, mang theo độ dài, không sở hữu dữ liệu | Truyền buffer an toàn giữa các hàm mà không copy — rất hữu ích khi parse dữ liệu mạng |
std::optional<T> (C++17) 🟢 | Biểu diễn giá trị “có thể không tồn tại” | Thay thế con trỏ nullptr hoặc giá trị sentinel để báo “không có kết quả” |
std::variant<T1,T2,...> (C++17) | Union kiểu an toàn (type-safe union) | Khi một biến có thể là một trong nhiều kiểu khác nhau |
std::pair / std::tuple | Gom nhóm nhiều giá trị | Trả về nhiều giá trị từ một hàm |
Method phổ biến trên container:
| Method | Công dụng |
|---|---|
.push_back(x) | Thêm phần tử vào cuối |
.emplace_back(args...) 🟢 | Xây dựng object trực tiếp tại chỗ trong container thay vì tạo object rồi copy/move vào — hiệu quả hơn push_back |
.reserve(n) | Cấp phát trước bộ nhớ cho n phần tử, tránh phải cấp phát lại nhiều lần khi thêm dần |
.size() / .empty() | Số lượng phần tử / kiểm tra rỗng |
.at(i) 🟢 | Truy cập phần tử có kiểm tra biên, ném std::out_of_range nếu sai — an toàn hơn operator[] |
operator[] | Truy cập nhanh, không kiểm tra biên — UB nếu truy cập sai chỉ số |
.find(key) | Tìm phần tử theo key (map/set), trả về iterator, so với .end() để biết có tìm thấy không |
.erase(it) | Xóa phần tử tại vị trí iterator |
.clear() | Xóa toàn bộ phần tử |
5. STL Algorithm phổ biến
Header
<algorithm>— các hàm thao tác trên container thông qua iterator, giúp code ngắn gọn và ít lỗi hơn viết vòng lặp tay.
| Hàm | Công dụng |
|---|---|
std::sort(begin, end) | Sắp xếp, độ phức tạp trung bình O(n log n) |
std::find(begin, end, value) | Tìm phần tử đầu tiên bằng value, trả về iterator (so với end() để biết có tìm thấy không) |
std::find_if(begin, end, pred) | Tìm phần tử đầu tiên thỏa điều kiện (lambda/hàm) |
std::count(begin, end, value) | Đếm số lần xuất hiện |
std::for_each(begin, end, fn) | Áp dụng hàm fn cho từng phần tử |
std::transform(begin, end, out, fn) | Áp dụng hàm biến đổi và ghi kết quả ra container khác |
std::accumulate(begin, end, init) | Tính tổng (hoặc gộp theo hàm tùy chỉnh) — header <numeric> |
std::all_of / any_of / none_of | Kiểm tra điều kiện cho toàn bộ / một phần / không phần tử nào |
std::unique(begin, end) | Loại bỏ phần tử trùng liên tiếp (cần sort trước nếu muốn loại trùng toàn bộ) |
std::remove_if(begin, end, pred) | “Dịch chuyển” phần tử không thỏa điều kiện lên đầu (không thực sự xóa khỏi container — cần kết hợp .erase(), gọi là erase-remove idiom) |
std::copy / std::move (algorithm) | Sao chép / di chuyển phần tử giữa các container |
std::clamp(v, lo, hi) (C++17) | Giới hạn giá trị trong khoảng [lo, hi] |
std::min / std::max / std::min_element / std::max_element | Tìm giá trị nhỏ nhất/lớn nhất |
// Erase-remove idiom — xóa toàn bộ phần tử thỏa điều kiện
std::vector<int> v = {1, 2, 3, 4, 5};
v.erase(std::remove_if(v.begin(), v.end(),
[](int x) { return x % 2 == 0; }),
v.end());
// v = {1, 3, 5}
6. Move semantics & Perfect forwarding
| Method/Từ khóa | Công dụng |
|---|---|
std::move(x) | Không di chuyển gì cả — chỉ là ép kiểu x thành rvalue reference, báo cho compiler biết “có thể lấy cắp tài nguyên của biến này”. Sau khi move, biến gốc ở trạng thái “hợp lệ nhưng không xác định giá trị” — không nên dùng lại. |
std::forward<T>(x) | Dùng trong template để “chuyển tiếp” đúng loại tham chiếu (lvalue/rvalue) tới hàm khác — nền tảng của perfect forwarding. |
Move constructor T(T&& other) | Constructor “lấy cắp” tài nguyên từ object tạm thời thay vì copy — hiệu quả hơn nhiều với object lớn (vector, string…). |
| RVO/NRVO (Return Value Optimization) | Compiler tự động tối ưu bỏ qua việc copy/move khi trả về object từ hàm — không cần viết return std::move(local_var) (thậm chí có thể làm mất tối ưu này). |
std::vector<int> big_vector = createLargeVector();
std::vector<int> another = std::move(big_vector);
// big_vector giờ ở trạng thái rỗng/không xác định, đừng dùng lại nó
7. Vào/Ra dữ liệu (I/O)
| Method | Header | Công dụng |
|---|---|---|
printf/scanf họ hàm | <cstdio> | I/O kiểu C, nhanh nhưng không type-safe — dễ lỗi format string (🔴 nguy cơ bảo mật nếu format string lấy từ input người dùng — “format string vulnerability”) |
std::cout / std::cin | <iostream> | I/O kiểu C++, type-safe hơn nhưng chậm hơn printf nếu không tắt sync với C stdio |
std::ifstream / std::ofstream | <fstream> | Đọc/ghi file, tự động quản lý tài nguyên theo RAII (đóng file khi ra khỏi scope) |
std::stringstream | <sstream> | Parse/format chuỗi qua giao diện stream — tiện khi tách token từ chuỗi |
std::ios::sync_with_stdio(false) | <iostream> | Tắt đồng bộ giữa iostream và stdio, tăng tốc I/O đáng kể khi không trộn printf và cout |
🔴 Lưu ý bảo mật: không bao giờ dùng dữ liệu từ input làm format string trực tiếp:
// SAI — format string vulnerability, kẻ tấn công có thể đọc/ghi bộ nhớ tùy ý qua %n, %x...
printf(user_input);
// ĐÚNG
printf("%s", user_input);
8. Đa luồng (Concurrency)
| Method | Header | Công dụng |
|---|---|---|
std::thread | <thread> | Tạo và quản lý một luồng thực thi mới |
.join() | Đợi thread kết thúc trước khi tiếp tục — bắt buộc gọi join() hoặc detach() trước khi thread object bị hủy, nếu không chương trình sẽ gọi std::terminate() | |
.detach() | Cho thread chạy độc lập, không cần chờ — cẩn trọng vì mất khả năng kiểm soát vòng đời | |
std::mutex | <mutex> | Khóa loại trừ (mutual exclusion) để bảo vệ dữ liệu chia sẻ giữa các thread |
std::lock_guard<std::mutex> 🟢 | <mutex> | RAII cho mutex — tự động lock() khi tạo, tự động unlock() khi ra khỏi scope. Nên dùng thay vì lock()/unlock() thủ công để tránh quên unlock khi có exception. |
std::unique_lock<std::mutex> | <mutex> | Giống lock_guard nhưng linh hoạt hơn (có thể unlock/lock lại giữa chừng, dùng với condition_variable) |
std::lock(m1, m2, ...) | <mutex> | Khóa nhiều mutex cùng lúc theo cách tránh deadlock (deadlock-avoidance algorithm) |
std::atomic<T> | <atomic> | Biến thao tác nguyên tử (atomic) không cần mutex — dùng cho kiểu dữ liệu đơn giản (int, bool, con trỏ) cần đọc/ghi an toàn giữa các thread với chi phí thấp hơn mutex |
std::condition_variable | <condition_variable> | Cơ chế cho một thread “chờ” đến khi có tín hiệu từ thread khác (producer-consumer pattern) |
std::async / std::future | <future> | Chạy hàm bất đồng bộ và lấy kết quả trả về sau (không cần tự quản lý thread thủ công) |
std::call_once | <mutex> | Đảm bảo một đoạn code chỉ chạy đúng một lần dù được gọi từ nhiều thread — dùng cho khởi tạo singleton an toàn |
std::mutex mtx;
int shared_counter = 0;
void increment() {
std::lock_guard<std::mutex> lock(mtx); // tự động unlock khi hàm kết thúc
++shared_counter;
}
9. Xử lý số & Bit
| Hàm/Toán tử | Header | Công dụng |
|---|---|---|
<< / >> / & / | / ^ / ~ | (toán tử) | Dịch bit trái/phải, AND, OR, XOR, NOT — dùng nhiều khi thao tác thanh ghi phần cứng, cờ trạng thái (flag), giao thức nhị phân |
std::bitset<N> | <bitset> | Biểu diễn và thao tác chuỗi bit có kích thước cố định, tiện hơn thao tác bit thủ công trên số nguyên |
std::numeric_limits<T>::max()/min() | <limits> | Lấy giá trị lớn nhất/nhỏ nhất của kiểu số — nên dùng thay vì hardcode (ví dụ tránh viết tay 2147483647) |
std::abs / std::round / std::floor / std::ceil | <cmath> | Các hàm toán học cơ bản |
std::gcd / std::lcm (C++17) | <numeric> | Ước chung lớn nhất / bội chung nhỏ nhất |
__builtin_popcount (GCC/Clang) | (built-in) | Đếm số bit 1 trong một số — tối ưu bằng lệnh CPU chuyên dụng nếu phần cứng hỗ trợ |
std::countl_zero / std::countr_zero (C++20) | <bit> | Đếm số bit 0 ở đầu/cuối — thay thế portable cho các hàm __builtin_* của compiler cụ thể |
10. Mạng, Byte order & Serialize
| Hàm | Header | Công dụng |
|---|---|---|
htons(x) / ntohs(x) | <arpa/inet.h> (POSIX) | Chuyển đổi số 16-bit giữa thứ tự byte host (máy tính đang chạy) và network (chuẩn big-endian dùng trong giao thức mạng) |
htonl(x) / ntohl(x) | <arpa/inet.h> | Tương tự nhưng cho số 32-bit |
inet_pton() / inet_ntop() | <arpa/inet.h> | Chuyển đổi giữa địa chỉ IP dạng chuỗi ("192.168.1.1") và dạng nhị phân — an toàn hơn hàm cũ inet_addr/inet_ntoa (hỗ trợ cả IPv6, thread-safe) |
memcpy (xem Mục 1) | <cstring> | Cách an toàn để đọc/ghi dữ liệu vào buffer mạng, tránh vi phạm alignment/strict aliasing |
std::span<std::byte> (C++20) | <span> | Biểu diễn buffer thô có kèm độ dài khi truyền giữa các hàm parse — an toàn hơn con trỏ + độ dài rời rạc |
// Ví dụ đọc một trường 16-bit từ gói tin nhận qua mạng
uint16_t length_network_order;
std::memcpy(&length_network_order, buffer + offset, sizeof(length_network_order));
uint16_t length = ntohs(length_network_order); // chuyển về thứ tự byte của máy hiện tại
11. Bảo mật / Crypto
| Hàm | Nguồn | Công dụng |
|---|---|---|
explicit_bzero(ptr, n) (glibc/BSD) hoặc memset_s (C11 Annex K) | Xóa vùng nhớ chứa dữ liệu nhạy cảm mà không bị compiler tối ưu bỏ qua — dùng thay memset khi xóa khóa/mật khẩu khỏi bộ nhớ | |
CRYPTO_memcmp() (OpenSSL) | OpenSSL | So sánh hai chuỗi byte với thời gian không đổi (constant-time), chống timing attack — dùng khi so sánh MAC, token, hash |
RAND_bytes() (OpenSSL) | OpenSSL | Sinh số ngẫu nhiên an toàn về mật mã (CSPRNG) — dùng cho khóa, nonce, salt. Không dùng rand() cho mục đích này vì dễ đoán được |
EVP_* API (OpenSSL) | OpenSSL | Bộ API thống nhất cho mã hóa đối xứng/bất đối xứng, hash, HMAC — nên dùng thay vì gọi trực tiếp các hàm thuật toán cụ thể (linh hoạt đổi thuật toán sau này) |
SHA256()/SHA3() họ hàm hash | OpenSSL/mbedTLS | Tính hash — dùng để kiểm tra toàn vẹn dữ liệu, không dùng để lưu mật khẩu trực tiếp (cần thuật toán chuyên cho mật khẩu như bcrypt/Argon2 có “salt” và “cost factor”) |
getrandom() (Linux syscall) | <sys/random.h> | Lấy số ngẫu nhiên trực tiếp từ kernel CSPRNG — an toàn hơn đọc /dev/urandom thủ công trong một số tình huống |
🔴 Nhắc lại nguyên tắc quan trọng nhất: không tự viết thuật toán mã hóa, luôn dùng thư viện đã kiểm định (OpenSSL, mbedTLS, wolfSSL cho embedded).
12. Kiểm tra lúc biên dịch & Debug
| Method/Từ khóa | Công dụng |
|---|---|
static_assert(condition, "message") 🟢 | Kiểm tra điều kiện ngay lúc biên dịch, báo lỗi build nếu sai — dùng để đảm bảo sizeof(struct) đúng như mong đợi khi map với giao thức/phần cứng |
assert(condition) | <cassert> — kiểm tra điều kiện lúc chạy (runtime), dừng chương trình nếu sai. Bị vô hiệu hóa khi build với NDEBUG (bản release) — không dùng để kiểm tra input từ người dùng/mạng (vì sẽ mất tác dụng ở production) |
[[nodiscard]] (C++17) | Đánh dấu hàm mà giá trị trả về không nên bị bỏ qua — compiler sẽ cảnh báo nếu người gọi quên kiểm tra (ví dụ hàm trả về mã lỗi) |
[[maybe_unused]] | Báo compiler không cảnh báo “biến/tham số không dùng đến” — hữu ích khi tham số chỉ cần cho một số cấu hình build |
typeid(x).name() | <typeinfo> — lấy tên kiểu lúc runtime (dùng với RTTI, hạn chế dùng trong embedded vì tăng kích thước binary) |
__FILE__ / __LINE__ / __func__ | Macro có sẵn của compiler, hữu ích khi viết log/assert tùy chỉnh để biết chính xác vị trí lỗi |
struct PacketHeader {
uint16_t length;
uint8_t type;
uint8_t flags;
};
static_assert(sizeof(PacketHeader) == 4, "PacketHeader phải đúng 4 byte để khớp giao thức");
13. Bảng tra nhanh: “Đừng dùng cái này — dùng cái kia”
| 🔴 Tránh dùng | 🟢 Dùng thay thế | Lý do |
|---|---|---|
strcpy, strcat, sprintf, gets | snprintf, std::string, std::span | Chống buffer overflow |
new/delete trần | std::make_unique/std::make_shared | Tránh leak khi có exception |
malloc không kiểm tra | malloc + kiểm tra NULL luôn luôn | Tránh crash âm thầm |
| Con trỏ thô để sở hữu tài nguyên | Smart pointer (unique_ptr/shared_ptr) | RAII, tự động giải phóng |
memcmp cho dữ liệu bảo mật | CRYPTO_memcmp (constant-time) | Chống timing attack |
memset để xóa secret | explicit_bzero/memset_s | Compiler không được tối ưu bỏ qua |
rand() cho khóa/token | RAND_bytes() (CSPRNG) | Chống đoán được giá trị |
(int)x (C-style cast) | static_cast<int>(x) | Rõ ràng, dễ tìm khi audit |
#define CONST 100 | constexpr int kConst = 100; | Có kiểm tra kiểu |
printf(user_input) | printf("%s", user_input) | Chống format string vulnerability |
| Tự viết crypto | Thư viện đã kiểm định (OpenSSL/mbedTLS) | Chống lỗi cài đặt tinh vi |
std::vector trong ISR/real-time path | std::array hoặc buffer tĩnh | Đảm bảo tính xác định (determinism) |
Xem thêm file nguyen-tac-lap-trinh-C-CPP.md để hiểu bối cảnh và nguyên tắc đầy đủ khi áp dụng các method này trong dự án embedded/RTOS/viễn thông/an ninh mạng.