Agent Skills by ALSEL
Anthropic Claudeその他⭐ リポ 0品質スコア 50/100

memory-safety-patterns

RAII、所有権、スマートポインタ、リソース管理などのパターンを活用し、Rust・C++・C でメモリ安全なプログラミングを実装します。安全なシステムコードの記述、リソース管理、メモリバグの防止が必要な際に使用してください。

description の原文を見る

Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.

SKILL.md 本文

メモリセーフティパターン

RAII、所有権、スマートポインタ、リソース管理を含むメモリセーフプログラミングの言語横断的なパターン。

このスキルを使う時

  • メモリセーフなシステムコードを書く
  • リソース(ファイル、ソケット、メモリ)を管理する
  • use-after-free とメモリリークを防ぐ
  • RAII パターンを実装する
  • 安全性のための言語選択
  • メモリ問題をデバッグする

コアコンセプト

1. メモリバグの分類

バグタイプ説明対策
Use-after-free解放されたメモリへのアクセス所有権、RAII
Double-free同じメモリを2回解放スマートポインタ
メモリリークメモリを解放しないRAII、GC
バッファオーバーフローバッファ末尾を超えて書込境界チェック
ダングリングポインタ解放されたメモリへのポインタ生存期間の追跡
データレース並行無同期アクセス所有権、Sync

2. セーフティスペクトラム

Manual (C) → Smart Pointers (C++) → Ownership (Rust) → GC (Go, Java)
Less safe                                              More safe
More control                                           Less control

言語別パターン

パターン 1: C++ の RAII

// RAII: Resource Acquisition Is Initialization
// リソースの生存期間はオブジェクトの生存期間に結びつく

#include <memory>
#include <fstream>
#include <mutex>

// RAII によるファイルハンドル
class FileHandle {
public:
    explicit FileHandle(const std::string& path)
        : file_(path) {
        if (!file_.is_open()) {
            throw std::runtime_error("Failed to open file");
        }
    }

    // デストラクタが自動的にファイルを閉じる
    ~FileHandle() = default; // fstream はそのデストラクタで閉じる

    // コピーを削除(double-close を防ぐ)
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;

    // ムーブを許可
    FileHandle(FileHandle&&) = default;
    FileHandle& operator=(FileHandle&&) = default;

    void write(const std::string& data) {
        file_ << data;
    }

private:
    std::fstream file_;
};

// ロックガード(ミューテックスの RAII)
class Database {
public:
    void update(const std::string& key, const std::string& value) {
        std::lock_guard<std::mutex> lock(mutex_); // スコープ終了時に解放
        data_[key] = value;
    }

    std::string get(const std::string& key) {
        std::shared_lock<std::shared_mutex> lock(shared_mutex_);
        return data_[key];
    }

private:
    std::mutex mutex_;
    std::shared_mutex shared_mutex_;
    std::map<std::string, std::string> data_;
};

// ロールバック機能付きトランザクション(RAII)
template<typename T>
class Transaction {
public:
    explicit Transaction(T& target)
        : target_(target), backup_(target), committed_(false) {}

    ~Transaction() {
        if (!committed_) {
            target_ = backup_; // ロールバック
        }
    }

    void commit() { committed_ = true; }

    T& get() { return target_; }

private:
    T& target_;
    T backup_;
    bool committed_;
};

パターン 2: C++ のスマートポインタ

#include <memory>

// unique_ptr: 単一所有権
class Engine {
public:
    void start() { /* ... */ }
};

class Car {
public:
    Car() : engine_(std::make_unique<Engine>()) {}

    void start() {
        engine_->start();
    }

    // 所有権の移譲
    std::unique_ptr<Engine> extractEngine() {
        return std::move(engine_);
    }

private:
    std::unique_ptr<Engine> engine_;
};

// shared_ptr: 共有所有権
class Node {
public:
    std::string data;
    std::shared_ptr<Node> next;

    // 循環参照を破るために weak_ptr を使用
    std::weak_ptr<Node> parent;
};

void sharedPtrExample() {
    auto node1 = std::make_shared<Node>();
    auto node2 = std::make_shared<Node>();

    node1->next = node2;
    node2->parent = node1; // weak_ptr 参照が循環参照を防ぐ

    // weak_ptr へのアクセス
    if (auto parent = node2->parent.lock()) {
        // parent は有効な shared_ptr
    }
}

// リソース用カスタムデリータ
class Socket {
public:
    static void close(int* fd) {
        if (fd && *fd >= 0) {
            ::close(*fd);
            delete fd;
        }
    }
};

auto createSocket() {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    return std::unique_ptr<int, decltype(&Socket::close)>(
        new int(fd),
        &Socket::close
    );
}

// make_unique/make_shared のベストプラクティス
void bestPractices() {
    // 良い例: 例外安全、単一割り当て
    auto ptr = std::make_shared<Widget>();

    // 悪い例: 2つの割り当て、例外安全ではない
    std::shared_ptr<Widget> ptr2(new Widget());

    // 配列の場合
    auto arr = std::make_unique<int[]>(10);
}

パターン 3: Rust の所有権

// ムーブセマンティクス(デフォルト)
fn move_example() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 は MOVE される、もう有効ではない

    // println!("{}", s1); // コンパイルエラー!
    println!("{}", s2);
}

// 借用(参照)
fn borrow_example() {
    let s = String::from("hello");

    // イミュータブル借用(複数許可)
    let len = calculate_length(&s);
    println!("{} has length {}", s, len);

    // ミュータブル借用(1つだけ許可)
    let mut s = String::from("hello");
    change(&mut s);
}

fn calculate_length(s: &String) -> usize {
    s.len()
} // s はスコープを抜けるが、借用されているので drop されない

fn change(s: &mut String) {
    s.push_str(", world");
}

// ライフタイム: コンパイラが参照の有効性を追跡
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

// 参照を含む構造体はライフタイムアノテーションが必要
struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    // ライフタイム省略: コンパイラが &self の 'a を推論
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention: {}", announcement);
        self.part
    }
}

// 内部可変性
use std::cell::{Cell, RefCell};
use std::rc::Rc;

struct Stats {
    count: Cell<i32>,           // Copy 型用
    data: RefCell<Vec<String>>, // Non-Copy 型用
}

impl Stats {
    fn increment(&self) {
        self.count.set(self.count.get() + 1);
    }

    fn add_data(&self, item: String) {
        self.data.borrow_mut().push(item);
    }
}

// 共有所有権用 Rc(シングルスレッド)
fn rc_example() {
    let data = Rc::new(vec![1, 2, 3]);
    let data2 = Rc::clone(&data); // 参照カウントをインクリメント

    println!("Count: {}", Rc::strong_count(&data)); // 2
}

// 共有所有権用 Arc(スレッドセーフ)
use std::sync::Arc;
use std::thread;

fn arc_example() {
    let data = Arc::new(vec![1, 2, 3]);

    let handles: Vec<_> = (0..3)
        .map(|_| {
            let data = Arc::clone(&data);
            thread::spawn(move || {
                println!("{:?}", data);
            })
        })
        .collect();

    for handle in handles {
        handle.join().unwrap();
    }
}

パターン 4: C での安全なリソース管理

// C には RAII がないが、パターンで対応できる

#include <stdlib.h>
#include <stdio.h>

// パターン: goto cleanup
int process_file(const char* path) {
    FILE* file = NULL;
    char* buffer = NULL;
    int result = -1;

    file = fopen(path, "r");
    if (!file) {
        goto cleanup;
    }

    buffer = malloc(1024);
    if (!buffer) {
        goto cleanup;
    }

    // ファイル処理...
    result = 0;

cleanup:
    if (buffer) free(buffer);
    if (file) fclose(file);
    return result;
}

// パターン: create/destroy を持つ不透明ポインタ
typedef struct Context Context;

Context* context_create(void);
void context_destroy(Context* ctx);
int context_process(Context* ctx, const char* data);

// 実装
struct Context {
    int* data;
    size_t size;
    FILE* log;
};

Context* context_create(void) {
    Context* ctx = calloc(1, sizeof(Context));
    if (!ctx) return NULL;

    ctx->data = malloc(100 * sizeof(int));
    if (!ctx->data) {
        free(ctx);
        return NULL;
    }

    ctx->log = fopen("log.txt", "w");
    if (!ctx->log) {
        free(ctx->data);
        free(ctx);
        return NULL;
    }

    return ctx;
}

void context_destroy(Context* ctx) {
    if (ctx) {
        if (ctx->log) fclose(ctx->log);
        if (ctx->data) free(ctx->data);
        free(ctx);
    }
}

// パターン: cleanup 属性(GCC/Clang 拡張)
#define AUTO_FREE __attribute__((cleanup(auto_free_func)))

void auto_free_func(void** ptr) {
    free(*ptr);
}

void auto_free_example(void) {
    AUTO_FREE char* buffer = malloc(1024);
    // buffer はスコープ終了時に自動解放される
}

パターン 5: 境界チェック

// C++: 生配列の代わりにコンテナを使用
#include <vector>
#include <array>
#include <span>

void safe_array_access() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // セーフ: std::out_of_range をスロー
    try {
        int val = vec.at(10);
    } catch (const std::out_of_range& e) {
        // エラーを処理
    }

    // アンセーフだがより高速(境界チェックなし)
    int val = vec[2];

    // モダン C++20: 配列ビューに対する std::span
    std::span<int> view(vec);
    // イテレータは境界セーフ
    for (int& x : view) {
        x *= 2;
    }
}

// 固定サイズ配列
void fixed_array() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};

    // コンパイル時にサイズが判明
    static_assert(arr.size() == 5);

    // セーフなアクセス
    int val = arr.at(2);
}
// Rust: デフォルトで境界チェック

fn rust_bounds_checking() {
    let vec = vec![1, 2, 3, 4, 5];

    // ランタイム境界チェック(範囲外なら panic)
    let val = vec[2];

    // 明示的なオプション(panic しない)
    match vec.get(10) {
        Some(val) => println!("Got {}", val),
        None => println!("Index out of bounds"),
    }

    // イテレータ(境界チェック不要)
    for val in &vec {
        println!("{}", val);
    }

    // スライスは境界チェック付き
    let slice = &vec[1..3]; // [2, 3]
}

パターン 6: データレースの防止

// C++: スレッドセーフな共有状態
#include <mutex>
#include <shared_mutex>
#include <atomic>

class ThreadSafeCounter {
public:
    void increment() {
        // アトミック操作
        count_.fetch_add(1, std::memory_order_relaxed);
    }

    int get() const {
        return count_.load(std::memory_order_relaxed);
    }

private:
    std::atomic<int> count_{0};
};

class ThreadSafeMap {
public:
    void write(const std::string& key, int value) {
        std::unique_lock lock(mutex_);
        data_[key] = value;
    }

    std::optional<int> read(const std::string& key) {
        std::shared_lock lock(mutex_);
        auto it = data_.find(key);
        if (it != data_.end()) {
            return it->second;
        }
        return std::nullopt;
    }

private:
    mutable std::shared_mutex mutex_;
    std::map<std::string, int> data_;
};
// Rust: コンパイル時のデータレース防止

use std::sync::{Arc, Mutex, RwLock};
use std::sync::atomic::{AtomicI32, Ordering};
use std::thread;

// シンプル型用アトミック
fn atomic_example() {
    let counter = Arc::new(AtomicI32::new(0));

    let handles: Vec<_> = (0..10)
        .map(|_| {
            let counter = Arc::clone(&counter);
            thread::spawn(move || {
                counter.fetch_add(1, Ordering::SeqCst);
            })
        })
        .collect();

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Counter: {}", counter.load(Ordering::SeqCst));
}

// 複雑な型用 Mutex
fn mutex_example() {
    let data = Arc::new(Mutex::new(vec![]));

    let handles: Vec<_> = (0..10)
        .map(|i| {
            let data = Arc::clone(&data);
            thread::spawn(move || {
                let mut vec = data.lock().unwrap();
                vec.push(i);
            })
        })
        .collect();

    for handle in handles {
        handle.join().unwrap();
    }
}

// 読み込みが多いワークロード用 RwLock
fn rwlock_example() {
    let data = Arc::new(RwLock::new(HashMap::new()));

    // 複数の読み込みは OK
    let read_guard = data.read().unwrap();

    // ライターが読み込み者をブロック
    let write_guard = data.write().unwrap();
}

ベストプラクティス

すること

  • RAII を優先する - リソース生存期間をスコープに結びつける
  • スマートポインタを使用する - C++ で生ポインタを避ける
  • 所有権を理解する - 誰が何を所有しているか知る
  • 境界をチェックする - セーフなアクセスメソッドを使用
  • ツールを使用する - AddressSanitizer、Valgrind、Miri

しないこと

  • 生ポインタを使用しない - C と相互作用する時を除き
  • ローカル参照を返さない - ダングリングポインタになる
  • コンパイラ警告を無視しない - バグを検出する
  • unsafe を無責任に使用しない - Rust で最小化する
  • スレッドセーフを仮定しない - 明示的に行う

デバッギングツール

# AddressSanitizer(Clang/GCC)
clang++ -fsanitize=address -g source.cpp

# Valgrind
valgrind --leak-check=full ./program

# Rust Miri(未定義動作検出器)
cargo +nightly miri run

# ThreadSanitizer
clang++ -fsanitize=thread -g source.cpp

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
wshobson
リポジトリ
wshobson/agents
ライセンス
MIT
最終更新
不明

Source: https://github.com/wshobson/agents / ライセンス: MIT

関連スキル

汎用その他⭐ リポ 1,982

superfluid

Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper

by LeoYeAI
汎用その他⭐ リポ 100

civ-finish-quotes

実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。

by huxiuhan
汎用その他⭐ リポ 1,110

nookplot

Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。

by BankrBot
汎用その他⭐ リポ 59

web3-polymarket

Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。

by elophanto
汎用その他⭐ リポ 52

ethskills

Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。

by jiayaoqijia
汎用その他⭐ リポ 44

xxyy-trade

このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。

by Jimmy-Holiday
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: wshobson · wshobson/agents · ライセンス: MIT